Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1034 lines
35 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996
  5. //
  6. // File: util.cxx
  7. //
  8. // Contents: Some misc helper functions
  9. //
  10. // History:
  11. //----------------------------------------------------------------------------
  12. #include "ldapc.hxx"
  13. #pragma hdrstop
  14. #if 0
  15. // ADsGetSearchPreference code
  16. //
  17. // Must explicitly include here since adshlp.h
  18. // is not #included.
  19. //
  20. #ifdef __cplusplus
  21. extern "C" {
  22. #endif
  23. HRESULT WINAPI
  24. ADsGetSearchPreference(
  25. ADS_SEARCH_HANDLE hSearchHandle,
  26. LPWSTR lpszPathName,
  27. PADS_SEARCHPREF_INFO *ppSearchPrefs,
  28. PDWORD pdwNumPrefs
  29. );
  30. #ifdef __cplusplus
  31. }
  32. #endif
  33. HRESULT
  34. UTF8ToUnicodeString(
  35. LPCSTR pUTF8,
  36. LPWSTR *ppUnicode
  37. );
  38. #endif
  39. //
  40. // The following table needs to be sorted
  41. //
  42. SEARCHENTRY g_aSyntaxSearchTable[] =
  43. {
  44. { TEXT("AccessPointDN"), LDAPTYPE_ACCESSPOINTDN }, // in NTDS, not in LDAP
  45. { TEXT("AttributeTypeDescription"), LDAPTYPE_ATTRIBUTETYPEDESCRIPTION },
  46. { TEXT("Audio"), LDAPTYPE_AUDIO },
  47. { TEXT("Binary"), LDAPTYPE_OCTETSTRING },
  48. { TEXT("BitString"), LDAPTYPE_BITSTRING },
  49. { TEXT("Boolean"), LDAPTYPE_BOOLEAN },
  50. { TEXT("CaseExactString") ,LDAPTYPE_CASEEXACTSTRING },
  51. { TEXT("CaseIgnoreString"),LDAPTYPE_CASEIGNORESTRING }, // in NTDS, not in LDAP RFC
  52. { TEXT("Certificate"), LDAPTYPE_CERTIFICATE },
  53. { TEXT("CertificateList"), LDAPTYPE_CERTIFICATELIST },
  54. { TEXT("CertificatePair"), LDAPTYPE_CERTIFICATEPAIR },
  55. { TEXT("Country"), LDAPTYPE_COUNTRYSTRING },
  56. { TEXT("DataQualitySyntax"),LDAPTYPE_DATAQUALITYSYNTAX },
  57. { TEXT("DeliveryMethod"), LDAPTYPE_DELIVERYMETHOD },
  58. { TEXT("DirectoryString"), LDAPTYPE_DIRECTORYSTRING },
  59. { TEXT("DN"), LDAPTYPE_DN },
  60. { TEXT("DSAQualitySyntax"),LDAPTYPE_DSAQUALITYSYNTAX },
  61. { TEXT("EnhancedGuide"), LDAPTYPE_ENHANCEDGUIDE },
  62. { TEXT("FacsimileTelephoneNumber"), LDAPTYPE_FACSIMILETELEPHONENUMBER },
  63. { TEXT("Fax"), LDAPTYPE_FAX },
  64. { TEXT("GeneralizedTime"), LDAPTYPE_GENERALIZEDTIME },
  65. { TEXT("Guide"), LDAPTYPE_GUIDE },
  66. { TEXT("IA5String"), LDAPTYPE_IA5STRING },
  67. { TEXT("INTEGER"), LDAPTYPE_INTEGER },
  68. { TEXT("INTEGER8"), LDAPTYPE_INTEGER8 }, // in NTDS, not in LDAP RFC
  69. { TEXT("JPEG"), LDAPTYPE_JPEG },
  70. { TEXT("MailPreference"), LDAPTYPE_MAILPREFERENCE },
  71. { TEXT("NameAndOptionalUID"), LDAPTYPE_NAMEANDOPTIONALUID },
  72. { TEXT("NumericString"), LDAPTYPE_NUMERICSTRING },
  73. { TEXT("ObjectClassDescription"), LDAPTYPE_OBJECTCLASSDESCRIPTION },
  74. { TEXT("ObjectSecurityDescriptor"), LDAPTYPE_SECURITY_DESCRIPTOR},
  75. { TEXT("OctetString"), LDAPTYPE_OCTETSTRING }, // in NTDS, not in LDAP RFC
  76. { TEXT("OID"), LDAPTYPE_OID },
  77. { TEXT("ORAddress"), LDAPTYPE_ORADDRESS },
  78. { TEXT("ORName"), LDAPTYPE_ORNAME }, // in NTDS, not in LDAP RFC
  79. { TEXT("OtherMailbox"), LDAPTYPE_OTHERMAILBOX },
  80. { TEXT("Password"), LDAPTYPE_PASSWORD },
  81. { TEXT("PostalAddress"), LDAPTYPE_POSTALADDRESS },
  82. { TEXT("PresentationAddress"), LDAPTYPE_PRESENTATIONADDRESS },
  83. { TEXT("PrintableString"), LDAPTYPE_PRINTABLESTRING },
  84. { TEXT("TelephoneNumber"), LDAPTYPE_TELEPHONENUMBER },
  85. { TEXT("TeletexTerminalIdentifier"), LDAPTYPE_TELETEXTERMINALIDENTIFIER },
  86. { TEXT("TelexNumber"), LDAPTYPE_TELEXNUMBER },
  87. //
  88. // Allegedly, "Time" started out as a bug in the schema (the correct description
  89. // is "GeneralizedTime"). However, we never delete items from the schema, so it
  90. // is still present in the current Whistler schema
  91. // (4/27/2000), so we'll keep in support for it.
  92. //
  93. { TEXT("Time"), LDAPTYPE_GENERALIZEDTIME },
  94. { TEXT("UTCTIME"), LDAPTYPE_UTCTIME }
  95. };
  96. DWORD g_nSyntaxSearchTableSize = ARRAY_SIZE(g_aSyntaxSearchTable );
  97. //
  98. // The following table needs to be sorted (lexicographically) on the first field
  99. //
  100. SEARCHENTRY g_aOidSyntaxSearchTable[] = {
  101. // the type is ORName a type of string -> mapped to string.
  102. { TEXT("1.2.840.113556.1.4.1221"), LDAPTYPE_CASEIGNORESTRING },
  103. // the type is Undefined syntax in the server, so we are defaulting.
  104. { TEXT("1.2.840.113556.1.4.1222"), LDAPTYPE_OCTETSTRING},
  105. { TEXT("1.2.840.113556.1.4.1362"), LDAPTYPE_CASEEXACTSTRING},
  106. { TEXT("1.2.840.113556.1.4.903"), LDAPTYPE_DNWITHBINARY},
  107. { TEXT("1.2.840.113556.1.4.904"), LDAPTYPE_DNWITHSTRING},
  108. { TEXT("1.2.840.113556.1.4.905"), LDAPTYPE_CASEIGNORESTRING },
  109. { TEXT("1.2.840.113556.1.4.906"), LDAPTYPE_INTEGER8 },
  110. { TEXT("1.2.840.113556.1.4.907"), LDAPTYPE_SECURITY_DESCRIPTOR },
  111. { TEXT("1.3.6.1.4.1.1466.115.121.1.10"), LDAPTYPE_CERTIFICATEPAIR },
  112. { TEXT("1.3.6.1.4.1.1466.115.121.1.11"), LDAPTYPE_COUNTRYSTRING },
  113. { TEXT("1.3.6.1.4.1.1466.115.121.1.12"), LDAPTYPE_DN },
  114. { TEXT("1.3.6.1.4.1.1466.115.121.1.13"), LDAPTYPE_DATAQUALITYSYNTAX },
  115. { TEXT("1.3.6.1.4.1.1466.115.121.1.14"), LDAPTYPE_DELIVERYMETHOD },
  116. { TEXT("1.3.6.1.4.1.1466.115.121.1.15"), LDAPTYPE_DIRECTORYSTRING },
  117. { TEXT("1.3.6.1.4.1.1466.115.121.1.19"), LDAPTYPE_DSAQUALITYSYNTAX },
  118. { TEXT("1.3.6.1.4.1.1466.115.121.1.2"), LDAPTYPE_ACCESSPOINTDN },
  119. { TEXT("1.3.6.1.4.1.1466.115.121.1.21"), LDAPTYPE_ENHANCEDGUIDE },
  120. { TEXT("1.3.6.1.4.1.1466.115.121.1.22"), LDAPTYPE_FACSIMILETELEPHONENUMBER },
  121. { TEXT("1.3.6.1.4.1.1466.115.121.1.23"), LDAPTYPE_FAX },
  122. { TEXT("1.3.6.1.4.1.1466.115.121.1.24"), LDAPTYPE_GENERALIZEDTIME },
  123. { TEXT("1.3.6.1.4.1.1466.115.121.1.25"), LDAPTYPE_GUIDE },
  124. { TEXT("1.3.6.1.4.1.1466.115.121.1.26"), LDAPTYPE_IA5STRING },
  125. { TEXT("1.3.6.1.4.1.1466.115.121.1.27"), LDAPTYPE_INTEGER },
  126. { TEXT("1.3.6.1.4.1.1466.115.121.1.28"), LDAPTYPE_JPEG },
  127. { TEXT("1.3.6.1.4.1.1466.115.121.1.3"), LDAPTYPE_ATTRIBUTETYPEDESCRIPTION },
  128. { TEXT("1.3.6.1.4.1.1466.115.121.1.32"), LDAPTYPE_MAILPREFERENCE },
  129. { TEXT("1.3.6.1.4.1.1466.115.121.1.33"), LDAPTYPE_ORADDRESS },
  130. { TEXT("1.3.6.1.4.1.1466.115.121.1.34"), LDAPTYPE_NAMEANDOPTIONALUID },
  131. { TEXT("1.3.6.1.4.1.1466.115.121.1.36"), LDAPTYPE_NUMERICSTRING },
  132. { TEXT("1.3.6.1.4.1.1466.115.121.1.37"), LDAPTYPE_OBJECTCLASSDESCRIPTION },
  133. { TEXT("1.3.6.1.4.1.1466.115.121.1.38"), LDAPTYPE_OID },
  134. { TEXT("1.3.6.1.4.1.1466.115.121.1.39"), LDAPTYPE_OTHERMAILBOX },
  135. { TEXT("1.3.6.1.4.1.1466.115.121.1.4"), LDAPTYPE_AUDIO },
  136. { TEXT("1.3.6.1.4.1.1466.115.121.1.40"), LDAPTYPE_OCTETSTRING },
  137. { TEXT("1.3.6.1.4.1.1466.115.121.1.41"), LDAPTYPE_POSTALADDRESS },
  138. { TEXT("1.3.6.1.4.1.1466.115.121.1.43"), LDAPTYPE_PRESENTATIONADDRESS },
  139. { TEXT("1.3.6.1.4.1.1466.115.121.1.44"), LDAPTYPE_PRINTABLESTRING },
  140. { TEXT("1.3.6.1.4.1.1466.115.121.1.5"), LDAPTYPE_OCTETSTRING },
  141. { TEXT("1.3.6.1.4.1.1466.115.121.1.50"), LDAPTYPE_TELEPHONENUMBER },
  142. { TEXT("1.3.6.1.4.1.1466.115.121.1.51"), LDAPTYPE_TELETEXTERMINALIDENTIFIER },
  143. { TEXT("1.3.6.1.4.1.1466.115.121.1.52"), LDAPTYPE_TELEXNUMBER },
  144. { TEXT("1.3.6.1.4.1.1466.115.121.1.53"), LDAPTYPE_UTCTIME },
  145. { TEXT("1.3.6.1.4.1.1466.115.121.1.6"), LDAPTYPE_BITSTRING },
  146. { TEXT("1.3.6.1.4.1.1466.115.121.1.7"), LDAPTYPE_BOOLEAN },
  147. { TEXT("1.3.6.1.4.1.1466.115.121.1.8"), LDAPTYPE_CERTIFICATE },
  148. { TEXT("1.3.6.1.4.1.1466.115.121.1.9"), LDAPTYPE_CERTIFICATELIST },
  149. };
  150. DWORD g_nOidSyntaxSearchTableSize = ARRAY_SIZE(g_aOidSyntaxSearchTable );
  151. DWORD
  152. GetSyntaxOfAttribute(
  153. LPWSTR pszAttrName,
  154. SCHEMAINFO *pSchemaInfo
  155. )
  156. {
  157. LPWSTR pszTemp = NULL;
  158. // Support for range attributes; for eg., objectClass=Range=0-1 We should
  159. // ignore everything after ';' inclusive.
  160. //
  161. if ((pszTemp = wcschr(pszAttrName, L';')) != NULL ) {
  162. *pszTemp = L'\0';
  163. }
  164. DWORD dwEntry = FindEntryInSearchTable( pszAttrName, pSchemaInfo->aPropertiesSearchTable, pSchemaInfo->nNumOfProperties * 2 );
  165. //
  166. // Put back the ; if we had replaced it.
  167. //
  168. if (pszTemp)
  169. *pszTemp = L';';
  170. if ( dwEntry != -1 )
  171. {
  172. DWORD dwSyntax = FindEntryInSearchTable( pSchemaInfo->aProperties[dwEntry].pszSyntax, g_aSyntaxSearchTable, ARRAY_SIZE(g_aSyntaxSearchTable) );
  173. if ( dwSyntax != -1 )
  174. return dwSyntax;
  175. }
  176. return LDAPTYPE_UNKNOWN;
  177. }
  178. DWORD
  179. LdapGetSyntaxIdFromName(
  180. LPWSTR pszSyntax
  181. )
  182. {
  183. DWORD dwSyntaxId;
  184. dwSyntaxId = FindEntryInSearchTable(
  185. pszSyntax,
  186. g_aSyntaxSearchTable,
  187. g_nSyntaxSearchTableSize );
  188. if ( dwSyntaxId == -1 ) {
  189. //
  190. // We need to look at the OID table before defaulting
  191. //
  192. dwSyntaxId = FindEntryInSearchTable(
  193. pszSyntax,
  194. g_aOidSyntaxSearchTable,
  195. g_nOidSyntaxSearchTableSize
  196. );
  197. }
  198. if (dwSyntaxId == -1 ) {
  199. dwSyntaxId = LDAPTYPE_UNKNOWN;
  200. }
  201. return dwSyntaxId;
  202. }
  203. HRESULT
  204. UnMarshallLDAPToLDAPSynID(
  205. LPWSTR pszAttrName,
  206. ADS_LDP *ld,
  207. LDAPMessage *entry,
  208. DWORD dwSyntax,
  209. LDAPOBJECTARRAY *pldapObjectArray
  210. )
  211. {
  212. HRESULT hr = S_OK;
  213. DWORD dwStatus = 0;
  214. int nNumberOfValues;
  215. switch ( dwSyntax ) {
  216. // The cases below are binary data
  217. case LDAPTYPE_OCTETSTRING:
  218. case LDAPTYPE_SECURITY_DESCRIPTOR:
  219. case LDAPTYPE_CERTIFICATE:
  220. case LDAPTYPE_CERTIFICATELIST:
  221. case LDAPTYPE_CERTIFICATEPAIR:
  222. case LDAPTYPE_PASSWORD:
  223. case LDAPTYPE_TELETEXTERMINALIDENTIFIER:
  224. case LDAPTYPE_AUDIO:
  225. case LDAPTYPE_JPEG:
  226. case LDAPTYPE_FAX:
  227. case LDAPTYPE_UNKNOWN:
  228. {
  229. struct berval **bValues = NULL;
  230. hr = LdapGetValuesLen( ld, entry, pszAttrName,
  231. &bValues, &nNumberOfValues );
  232. BAIL_ON_FAILURE(hr);
  233. pldapObjectArray->fIsString = FALSE;
  234. pldapObjectArray->dwCount = nNumberOfValues;
  235. pldapObjectArray->pLdapObjects = (PLDAPOBJECT) bValues;
  236. break;
  237. }
  238. // otherwise it is a string
  239. default:
  240. {
  241. TCHAR **strValues = NULL;
  242. hr = LdapGetValues( ld, entry, pszAttrName,
  243. &strValues, &nNumberOfValues );
  244. BAIL_ON_FAILURE(hr);
  245. pldapObjectArray->fIsString = TRUE;
  246. pldapObjectArray->dwCount = nNumberOfValues;
  247. pldapObjectArray->pLdapObjects = (PLDAPOBJECT) strValues;
  248. break;
  249. }
  250. }
  251. error:
  252. RRETURN(hr);
  253. }
  254. #if 0
  255. // ADsGetSearchPreference code
  256. HRESULT WINAPI
  257. ADsGetSearchPreference(
  258. ADS_SEARCH_HANDLE hSearchHandle,
  259. LPWSTR lpszPathName,
  260. PADS_SEARCHPREF_INFO *ppSearchPrefs,
  261. PDWORD pdwNumPrefs
  262. )
  263. {
  264. HRESULT hr = S_OK;
  265. OBJECTINFO ObjectInfo;
  266. POBJECTINFO pObjectInfo = &ObjectInfo;
  267. PLDAP_SEARCHINFO phSearchInfo= (PLDAP_SEARCHINFO) hSearchHandle;
  268. PLDAP_SEARCH_PREF pSearchPref = NULL;
  269. PADS_SEARCHPREF_INFO pADsSearchPref = NULL;
  270. PBYTE pbExtra = NULL;
  271. DWORD dwNumberPrefs = 0;
  272. DWORD dwNumberExtraBytes = 0;
  273. //
  274. // sanity check
  275. //
  276. if (!lpszPathName || !ppSearchPrefs || !phSearchInfo || !pdwNumPrefs)
  277. RRETURN(E_INVALIDARG);
  278. *ppSearchPrefs = NULL;
  279. *pdwNumPrefs = 0;
  280. //
  281. // Make sure we're being called on an LDAP path
  282. //
  283. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  284. hr = ADsObject(lpszPathName, pObjectInfo);
  285. BAIL_ON_FAILURE(hr);
  286. if (_tcscmp(pObjectInfo->ProviderName, szProviderName) != 0) {
  287. BAIL_ON_FAILURE(hr = E_NOTIMPL);
  288. }
  289. //
  290. // allocate space for the ADS_SEARCHPREF_INFO array we're
  291. // going to build
  292. //
  293. pSearchPref = &(phSearchInfo->_SearchPref);
  294. hr = CalcSpaceForSearchPrefs(pSearchPref, &dwNumberPrefs, &dwNumberExtraBytes);
  295. BAIL_ON_FAILURE(hr);
  296. // no search prefs were set
  297. if (dwNumberPrefs == 0) {
  298. *ppSearchPrefs = NULL;
  299. FreeObjectInfo(pObjectInfo);
  300. RRETURN(S_OK);
  301. }
  302. pADsSearchPref = (PADS_SEARCHPREF_INFO) AllocADsMem( (dwNumberPrefs * sizeof(ADS_SEARCHPREF_INFO)) + dwNumberExtraBytes);
  303. if (!pADsSearchPref)
  304. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  305. pbExtra = ((PBYTE)pADsSearchPref) + (dwNumberPrefs * sizeof(ADS_SEARCHPREF_INFO));
  306. //
  307. // construct the array of search prefs
  308. //
  309. hr = ConstructSearchPrefArray(pSearchPref, pADsSearchPref, pbExtra);
  310. BAIL_ON_FAILURE(hr);
  311. *ppSearchPrefs = pADsSearchPref;
  312. *pdwNumPrefs = dwNumberPrefs;
  313. FreeObjectInfo(pObjectInfo);
  314. RRETURN(hr);
  315. error:
  316. if (pADsSearchPref)
  317. FreeADsMem(pADsSearchPref);
  318. if (pObjectInfo) {
  319. FreeObjectInfo(pObjectInfo);
  320. }
  321. RRETURN(hr);
  322. }
  323. HRESULT
  324. ConstructSearchPrefArray(
  325. PLDAP_SEARCH_PREF pPrefs,
  326. PADS_SEARCHPREF_INFO pADsSearchPref,
  327. PBYTE pbExtraBytes
  328. )
  329. {
  330. HRESULT hr = S_OK;
  331. BOOL fDefault;
  332. LPSTR pUTF8 = NULL;
  333. LPWSTR pUnicode = NULL;
  334. if (!pPrefs || !pADsSearchPref || !pbExtraBytes)
  335. RRETURN(E_INVALIDARG);
  336. // ADS_SEARCHPREF_ASYNCHRONOUS
  337. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ASYNCHRONOUS,
  338. pPrefs,
  339. &fDefault));
  340. if (!fDefault) {
  341. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_ASYNCHRONOUS;
  342. pADsSearchPref->vValue.dwType = ADSTYPE_BOOLEAN;
  343. pADsSearchPref->vValue.Boolean = pPrefs->_fAsynchronous;
  344. pADsSearchPref++;
  345. }
  346. // ADS_SEARCHPREF_DEREF_ALIASES
  347. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_DEREF_ALIASES,
  348. pPrefs,
  349. &fDefault));
  350. if (!fDefault) {
  351. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_DEREF_ALIASES;
  352. pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
  353. pADsSearchPref->vValue.Integer = pPrefs->_dwDerefAliases;
  354. pADsSearchPref++;
  355. }
  356. // ADS_SEARCHPREF_SIZE_LIMIT
  357. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SIZE_LIMIT,
  358. pPrefs,
  359. &fDefault));
  360. if (!fDefault) {
  361. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_SIZE_LIMIT;
  362. pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
  363. pADsSearchPref->vValue.Integer = pPrefs->_dwSizeLimit;
  364. pADsSearchPref++;
  365. }
  366. // ADS_SEARCHPREF_TIME_LIMIT
  367. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TIME_LIMIT,
  368. pPrefs,
  369. &fDefault));
  370. if (!fDefault) {
  371. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_TIME_LIMIT;
  372. pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
  373. pADsSearchPref->vValue.Integer = pPrefs->_dwTimeLimit;
  374. pADsSearchPref++;
  375. }
  376. // ADS_SEARCHPREF_ATTRIBTYPES_ONLY
  377. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ATTRIBTYPES_ONLY,
  378. pPrefs,
  379. &fDefault));
  380. if (!fDefault) {
  381. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_ATTRIBTYPES_ONLY;
  382. pADsSearchPref->vValue.dwType = ADSTYPE_BOOLEAN;
  383. pADsSearchPref->vValue.Boolean = pPrefs->_fAttrsOnly;
  384. pADsSearchPref++;
  385. }
  386. // ADS_SEARCHPREF_SEARCH_SCOPE
  387. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SEARCH_SCOPE,
  388. pPrefs,
  389. &fDefault));
  390. if (!fDefault) {
  391. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  392. pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
  393. switch(pPrefs->_dwSearchScope) {
  394. case LDAP_SCOPE_SUBTREE:
  395. pADsSearchPref->vValue.Integer = ADS_SCOPE_SUBTREE;
  396. break;
  397. case LDAP_SCOPE_ONELEVEL:
  398. pADsSearchPref->vValue.Integer = ADS_SCOPE_ONELEVEL;
  399. break;
  400. case LDAP_SCOPE_BASE:
  401. pADsSearchPref->vValue.Integer = ADS_SCOPE_BASE;
  402. break;
  403. }
  404. pADsSearchPref++;
  405. }
  406. // ADS_SEARCHPREF_TIMEOUT
  407. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TIMEOUT,
  408. pPrefs,
  409. &fDefault));
  410. if (!fDefault) {
  411. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_TIMEOUT;
  412. pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
  413. pADsSearchPref->vValue.Integer = pPrefs->_timeout.tv_sec;
  414. pADsSearchPref++;
  415. }
  416. // ADS_SEARCHPREF_PAGESIZE
  417. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_PAGESIZE,
  418. pPrefs,
  419. &fDefault));
  420. if (!fDefault) {
  421. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  422. pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
  423. pADsSearchPref->vValue.Integer = pPrefs->_dwPageSize;
  424. pADsSearchPref++;
  425. }
  426. // ADS_SEARCHPREF_PAGED_TIME_LIMIT
  427. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_PAGED_TIME_LIMIT,
  428. pPrefs,
  429. &fDefault));
  430. if (!fDefault) {
  431. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_PAGED_TIME_LIMIT;
  432. pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
  433. pADsSearchPref->vValue.Integer = pPrefs->_dwPagedTimeLimit;
  434. pADsSearchPref++;
  435. }
  436. // ADS_SEARCHPREF_CHASE_REFERRALS
  437. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_CHASE_REFERRALS,
  438. pPrefs,
  439. &fDefault));
  440. if (!fDefault) {
  441. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_CHASE_REFERRALS;
  442. pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
  443. switch(pPrefs->_dwChaseReferrals) {
  444. case (DWORD) (DWORD_PTR)LDAP_OPT_OFF:
  445. pADsSearchPref->vValue.Integer = ADS_CHASE_REFERRALS_NEVER;
  446. break;
  447. case LDAP_CHASE_SUBORDINATE_REFERRALS:
  448. pADsSearchPref->vValue.Integer = ADS_CHASE_REFERRALS_SUBORDINATE;
  449. break;
  450. case LDAP_CHASE_EXTERNAL_REFERRALS:
  451. pADsSearchPref->vValue.Integer = ADS_CHASE_REFERRALS_EXTERNAL;
  452. break;
  453. case (DWORD) (DWORD_PTR) LDAP_OPT_ON:
  454. pADsSearchPref->vValue.Integer = ADS_CHASE_REFERRALS_ALWAYS;
  455. break;
  456. }
  457. pADsSearchPref++;
  458. }
  459. // ADS_SEARCHPREF_CACHE_RESULTS
  460. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_CACHE_RESULTS,
  461. pPrefs,
  462. &fDefault));
  463. if (!fDefault) {
  464. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_CACHE_RESULTS;
  465. pADsSearchPref->vValue.dwType = ADSTYPE_BOOLEAN;
  466. pADsSearchPref->vValue.Boolean = pPrefs->_fCacheResults;
  467. pADsSearchPref++;
  468. }
  469. // ADS_SEARCHPREF_TOMBSTONE
  470. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TOMBSTONE,
  471. pPrefs,
  472. &fDefault));
  473. if (!fDefault) {
  474. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_TOMBSTONE;
  475. pADsSearchPref->vValue.dwType = ADSTYPE_BOOLEAN;
  476. pADsSearchPref->vValue.Boolean = pPrefs->_fTombStone;
  477. pADsSearchPref++;
  478. }
  479. // ADS_SEARCHPREF_DIRSYNC
  480. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_DIRSYNC,
  481. pPrefs,
  482. &fDefault));
  483. if (!fDefault) {
  484. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_DIRSYNC;
  485. pADsSearchPref->vValue.dwType = ADSTYPE_PROV_SPECIFIC;
  486. pADsSearchPref->vValue.ProviderSpecific.dwLength = 0;
  487. pADsSearchPref->vValue.ProviderSpecific.lpValue = NULL;
  488. if (pPrefs->_pProvSpecific && pPrefs->_pProvSpecific->lpValue) {
  489. memcpy(pbExtraBytes, pPrefs->_pProvSpecific->lpValue, pPrefs->_pProvSpecific->dwLength);
  490. pADsSearchPref->vValue.ProviderSpecific.lpValue = pbExtraBytes;
  491. pADsSearchPref->vValue.ProviderSpecific.dwLength = pPrefs->_pProvSpecific->dwLength;
  492. pbExtraBytes += pPrefs->_pProvSpecific->dwLength;
  493. }
  494. pADsSearchPref++;
  495. }
  496. // ADS_SEARCHPREF_VLV
  497. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_VLV,
  498. pPrefs,
  499. &fDefault));
  500. if (!fDefault) {
  501. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_VLV;
  502. pADsSearchPref->vValue.dwType = ADSTYPE_PROV_SPECIFIC;
  503. pADsSearchPref->vValue.ProviderSpecific.dwLength = sizeof(ADS_VLV);
  504. pADsSearchPref->vValue.ProviderSpecific.lpValue = pbExtraBytes;
  505. PADS_VLV pADsVLV = (PADS_VLV) pbExtraBytes;
  506. pbExtraBytes += sizeof(ADS_VLV);
  507. pADsVLV->dwBeforeCount = pPrefs->_pVLVInfo->ldvlv_before_count;
  508. pADsVLV->dwAfterCount = pPrefs->_pVLVInfo->ldvlv_after_count;
  509. pADsVLV->dwOffset = pPrefs->_pVLVInfo->ldvlv_offset;
  510. pADsVLV->dwContentCount = pPrefs->_pVLVInfo->ldvlv_count;
  511. pADsVLV->pszTarget = NULL;
  512. pADsVLV->lpContextID = NULL;
  513. pADsVLV->dwContextIDLength = 0;
  514. if (pPrefs->_pVLVInfo->ldvlv_attrvalue && pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_val) {
  515. // As stored, the attribute is a non-terminated UTF-8 string.
  516. // We need to return a NULL-terminated Unicode string.
  517. // We do this by constructing a NULL-terminated UTF-8 string, and then
  518. // converting that to a Unicode string.
  519. pUTF8 = (PCHAR) AllocADsMem(pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_len + 1);
  520. if (!pUTF8)
  521. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  522. memcpy(pUTF8,
  523. pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_val,
  524. pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_len);
  525. pUTF8[pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_len] = '\0';
  526. hr = UTF8ToUnicodeString(pUTF8, &pUnicode);
  527. BAIL_ON_FAILURE(hr);
  528. memcpy(pbExtraBytes,
  529. pUnicode,
  530. (wcslen(pUnicode)+1) * sizeof(WCHAR));
  531. pADsVLV->pszTarget = (LPWSTR) pbExtraBytes;
  532. pbExtraBytes += (wcslen(pUnicode)+1) * sizeof(WCHAR);
  533. }
  534. if (pPrefs->_pVLVInfo->ldvlv_context && pPrefs->_pVLVInfo->ldvlv_context->bv_val) {
  535. memcpy(pbExtraBytes,
  536. pPrefs->_pVLVInfo->ldvlv_context->bv_val,
  537. pPrefs->_pVLVInfo->ldvlv_context->bv_len);
  538. pADsVLV->lpContextID = pbExtraBytes;
  539. pADsVLV->dwContextIDLength = pPrefs->_pVLVInfo->ldvlv_context->bv_len;
  540. pbExtraBytes += pPrefs->_pVLVInfo->ldvlv_context->bv_len;
  541. }
  542. pADsSearchPref++;
  543. }
  544. // ADS_SEARCHPREF_SORT_ON
  545. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SORT_ON,
  546. pPrefs,
  547. &fDefault));
  548. if (!fDefault) {
  549. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_SORT_ON;
  550. pADsSearchPref->vValue.dwType = ADSTYPE_PROV_SPECIFIC;
  551. pADsSearchPref->vValue.ProviderSpecific.dwLength = sizeof(ADS_SORTKEY) * pPrefs->_nSortKeys;
  552. pADsSearchPref->vValue.ProviderSpecific.lpValue = pbExtraBytes;
  553. PADS_SORTKEY pSortKeys = (PADS_SORTKEY) pbExtraBytes;
  554. pbExtraBytes += (sizeof(ADS_SORTKEY) * pPrefs->_nSortKeys);
  555. DWORD i;
  556. for (i=0; i < pPrefs->_nSortKeys; i++) {
  557. pSortKeys[i].fReverseorder = pPrefs->_pSortKeys[i].sk_reverseorder;
  558. pSortKeys[i].pszReserved = pPrefs->_pSortKeys[i].sk_matchruleoid;
  559. pSortKeys[i].pszAttrType = (LPWSTR) pbExtraBytes;
  560. memcpy(pbExtraBytes,
  561. pPrefs->_pSortKeys[i].sk_attrtype,
  562. (wcslen(pPrefs->_pSortKeys[i].sk_attrtype)+1) * sizeof(WCHAR)
  563. );
  564. pbExtraBytes += (wcslen(pPrefs->_pSortKeys[i].sk_attrtype)+1) * sizeof(WCHAR);
  565. }
  566. pADsSearchPref++;
  567. }
  568. // ADS_SEARCHPREF_ATTRIBUTE_QUERY
  569. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ATTRIBUTE_QUERY,
  570. pPrefs,
  571. &fDefault));
  572. if (!fDefault) {
  573. pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_ATTRIBUTE_QUERY;
  574. pADsSearchPref->vValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
  575. pADsSearchPref->vValue.CaseIgnoreString = pbExtraBytes;
  576. // copy SourceAttribute
  577. DWORD dwLen = (wcslen(pPrefs->_pAttribScoped) + 1) * sizeof(WCHAR);
  578. memcpy(pbExtraBytes,
  579. pPrefs->_pAttribScoped,
  580. dwLen);
  581. pbExtraBytes += dwLen ;
  582. pADsSearchPref++;
  583. }
  584. error:
  585. if (pUTF8)
  586. FreeADsMem(pUTF8);
  587. if (pUnicode)
  588. FreeADsMem(pUnicode);
  589. RRETURN(hr);
  590. }
  591. HRESULT
  592. CalcSpaceForSearchPrefs(
  593. PLDAP_SEARCH_PREF pPrefs,
  594. PDWORD pdwNumberPrefs,
  595. PDWORD pdwNumberExtraBytes
  596. )
  597. {
  598. if (!pPrefs || !pdwNumberPrefs || !pdwNumberExtraBytes)
  599. RRETURN(E_INVALIDARG);
  600. *pdwNumberPrefs = 0;
  601. *pdwNumberExtraBytes = 0;
  602. //
  603. // Calculate the number of ADS_SEARCHPREF_INFOs required
  604. // for search prefs that do _not_ require extra space.
  605. // (Currently, only _SORT_ON, _DIRSYNC, _VLV, _ATTRIBUTE_QUERY
  606. // require extra space).
  607. //
  608. // A ADS_SEARCHPREF_INFO is "required" if the corresponding
  609. // search pref is not set to its default value, as determined
  610. // by IsSearchPrefSetToDefault.
  611. //
  612. BOOL fDefault;
  613. HRESULT hr = S_OK;
  614. // ADS_SEARCHPREF_ASYNCHRONOUS
  615. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ASYNCHRONOUS,
  616. pPrefs,
  617. &fDefault));
  618. if (!fDefault)
  619. (*pdwNumberPrefs)++;
  620. // ADS_SEARCHPREF_DEREF_ALIASES
  621. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_DEREF_ALIASES,
  622. pPrefs,
  623. &fDefault));
  624. if (!fDefault)
  625. (*pdwNumberPrefs)++;
  626. // ADS_SEARCHPREF_SIZE_LIMIT
  627. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SIZE_LIMIT,
  628. pPrefs,
  629. &fDefault));
  630. if (!fDefault)
  631. (*pdwNumberPrefs)++;
  632. // ADS_SEARCHPREF_TIME_LIMIT
  633. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TIME_LIMIT,
  634. pPrefs,
  635. &fDefault));
  636. if (!fDefault)
  637. (*pdwNumberPrefs)++;
  638. // ADS_SEARCHPREF_ATTRIBTYPES_ONLY
  639. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ATTRIBTYPES_ONLY,
  640. pPrefs,
  641. &fDefault));
  642. if (!fDefault)
  643. (*pdwNumberPrefs)++;
  644. // ADS_SEARCHPREF_SEARCH_SCOPE
  645. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SEARCH_SCOPE,
  646. pPrefs,
  647. &fDefault));
  648. if (!fDefault)
  649. (*pdwNumberPrefs)++;
  650. // ADS_SEARCHPREF_TIMEOUT
  651. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TIMEOUT,
  652. pPrefs,
  653. &fDefault));
  654. if (!fDefault)
  655. (*pdwNumberPrefs)++;
  656. // ADS_SEARCHPREF_PAGESIZE
  657. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_PAGESIZE,
  658. pPrefs,
  659. &fDefault));
  660. if (!fDefault)
  661. (*pdwNumberPrefs)++;
  662. // ADS_SEARCHPREF_PAGED_TIME_LIMIT
  663. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_PAGED_TIME_LIMIT,
  664. pPrefs,
  665. &fDefault));
  666. if (!fDefault)
  667. (*pdwNumberPrefs)++;
  668. // ADS_SEARCHPREF_CHASE_REFERRALS
  669. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_CHASE_REFERRALS,
  670. pPrefs,
  671. &fDefault));
  672. if (!fDefault)
  673. (*pdwNumberPrefs)++;
  674. // ADS_SEARCHPREF_CACHE_RESULTS
  675. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_CACHE_RESULTS,
  676. pPrefs,
  677. &fDefault));
  678. if (!fDefault)
  679. (*pdwNumberPrefs)++;
  680. // ADS_SEARCHPREF_TOMBSTONE
  681. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TOMBSTONE,
  682. pPrefs,
  683. &fDefault));
  684. if (!fDefault)
  685. (*pdwNumberPrefs)++;
  686. //
  687. // _VLV, _DIRSYNC, _ATTRIBUTE_QUERY, and _SORT_ON require extra space in addition
  688. // to the ADS_SEARCHPREF_INFO structure.
  689. //
  690. // ADS_SEARCHPREF_DIRSYNC
  691. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_DIRSYNC,
  692. pPrefs,
  693. &fDefault));
  694. if (!fDefault) {
  695. (*pdwNumberPrefs)++;
  696. if (pPrefs->_pProvSpecific && pPrefs->_pProvSpecific->dwLength > 0) {
  697. *pdwNumberExtraBytes += pPrefs->_pProvSpecific->dwLength;
  698. }
  699. }
  700. // ADS_SEARCHPREF_VLV
  701. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_VLV,
  702. pPrefs,
  703. &fDefault));
  704. if (!fDefault) {
  705. (*pdwNumberPrefs)++;
  706. *pdwNumberExtraBytes += sizeof(ADS_VLV);
  707. if (pPrefs->_pVLVInfo->ldvlv_context) {
  708. *pdwNumberExtraBytes += pPrefs->_pVLVInfo->ldvlv_context->bv_len;
  709. }
  710. if (pPrefs->_pVLVInfo->ldvlv_attrvalue) {
  711. // As stored, the string is a UTF-8 string that is not NULL-terminated.
  712. // We need to calculate the size of a NULL-terminated Unicode string.
  713. int cch = MultiByteToWideChar(CP_UTF8,
  714. 0,
  715. pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_val,
  716. pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_len,
  717. NULL,
  718. 0);
  719. if (!cch)
  720. BAIL_ON_FAILURE(hr = E_FAIL);
  721. // add one WCHAR for NULL terminator
  722. *pdwNumberExtraBytes += ((cch*sizeof(WCHAR)) + sizeof(WCHAR));
  723. }
  724. }
  725. // ADS_SEARCHPREF_SORT_ON
  726. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SORT_ON,
  727. pPrefs,
  728. &fDefault));
  729. if (!fDefault) {
  730. (*pdwNumberPrefs)++;
  731. *pdwNumberExtraBytes += (sizeof(ADS_SORTKEY) * pPrefs->_nSortKeys);
  732. DWORD i;
  733. for (i=0; i<pPrefs->_nSortKeys; i++) {
  734. *pdwNumberExtraBytes += ((wcslen(pPrefs->_pSortKeys[i].sk_attrtype)+1) * sizeof(WCHAR));
  735. }
  736. }
  737. // ADS_SEARCHPREF_ATTRIBUTE_QUERY
  738. BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ATTRIBUTE_QUERY,
  739. pPrefs,
  740. &fDefault));
  741. if (!fDefault) {
  742. (*pdwNumberPrefs)++;
  743. *pdwNumberExtraBytes += ((wcslen(pPrefs->_pAttribScoped) + 1) * sizeof(WCHAR));
  744. }
  745. error:
  746. RRETURN(hr);
  747. }
  748. //
  749. // This function tests whether a given search pref is set
  750. // to it's default value.
  751. //
  752. // Important: This function considers the "default value"
  753. // to be the value currently set in CLDAPGenObject::InitSearchPrefs.
  754. // If you ever change those defaults, update this function.
  755. //
  756. HRESULT
  757. IsSearchPrefSetToDefault(
  758. ADS_SEARCHPREF_ENUM pref,
  759. PLDAP_SEARCH_PREF pPrefs,
  760. PBOOL pfDefault
  761. )
  762. {
  763. if (!pPrefs || !pfDefault)
  764. RRETURN(E_INVALIDARG);
  765. *pfDefault = TRUE;
  766. switch(pref) {
  767. case ADS_SEARCHPREF_ASYNCHRONOUS:
  768. // default: not async
  769. if (pPrefs->_fAsynchronous)
  770. *pfDefault = FALSE;
  771. break;
  772. case ADS_SEARCHPREF_DEREF_ALIASES:
  773. // default: do not deref
  774. if (pPrefs->_dwDerefAliases)
  775. *pfDefault = FALSE;
  776. break;
  777. case ADS_SEARCHPREF_SIZE_LIMIT:
  778. // default: no size limit
  779. if (pPrefs->_dwSizeLimit)
  780. *pfDefault = FALSE;
  781. break;
  782. case ADS_SEARCHPREF_TIME_LIMIT:
  783. // default: no time limit
  784. if (pPrefs->_dwTimeLimit)
  785. *pfDefault = FALSE;
  786. break;
  787. case ADS_SEARCHPREF_ATTRIBTYPES_ONLY:
  788. // default: not attribtypes only
  789. if (pPrefs->_fAttrsOnly)
  790. *pfDefault = FALSE;
  791. break;
  792. case ADS_SEARCHPREF_SEARCH_SCOPE:
  793. // default: LDAP_SCOPE_SUBTREE
  794. if (pPrefs->_dwSearchScope != LDAP_SCOPE_SUBTREE)
  795. *pfDefault = FALSE;
  796. break;
  797. case ADS_SEARCHPREF_TIMEOUT:
  798. // default: no timeout
  799. if (pPrefs->_timeout.tv_sec || pPrefs->_timeout.tv_usec)
  800. *pfDefault = FALSE;
  801. break;
  802. case ADS_SEARCHPREF_PAGESIZE:
  803. // default: no pagesize
  804. if (pPrefs->_dwPageSize)
  805. *pfDefault = FALSE;
  806. break;
  807. case ADS_SEARCHPREF_PAGED_TIME_LIMIT:
  808. // default: no paged time limit
  809. if (pPrefs->_dwPagedTimeLimit)
  810. *pfDefault = FALSE;
  811. break;
  812. case ADS_SEARCHPREF_CHASE_REFERRALS:
  813. // default: ADS_CHASE_REFERRALS_EXTERNAL
  814. if (pPrefs->_dwChaseReferrals != ADS_CHASE_REFERRALS_EXTERNAL)
  815. *pfDefault = FALSE;
  816. break;
  817. case ADS_SEARCHPREF_SORT_ON:
  818. // default: no sorting
  819. if (pPrefs->_pSortKeys)
  820. *pfDefault = FALSE;
  821. break;
  822. case ADS_SEARCHPREF_CACHE_RESULTS:
  823. // default: cache results
  824. if (!pPrefs->_fCacheResults)
  825. *pfDefault = FALSE;
  826. break;
  827. case ADS_SEARCHPREF_DIRSYNC:
  828. // default: not a dirsync search
  829. if (pPrefs->_fDirSync)
  830. *pfDefault = FALSE;
  831. break;
  832. case ADS_SEARCHPREF_TOMBSTONE:
  833. // default: don't include tombstones
  834. if (pPrefs->_fTombStone)
  835. *pfDefault = FALSE;
  836. break;
  837. case ADS_SEARCHPREF_VLV:
  838. // default: not a VLV search
  839. if (pPrefs->_pVLVInfo)
  840. *pfDefault = FALSE;
  841. break;
  842. case ADS_SEARCHPREF_ATTRIBUTE_QUERY:
  843. // default: not an attribute-scoped query search
  844. if (pPrefs->_pAttribScoped)
  845. *pfDefault = FALSE;
  846. break;
  847. default:
  848. RRETURN(E_INVALIDARG);
  849. }
  850. RRETURN(S_OK);
  851. }
  852. #endif