adsldp: Sort the attribute types array.

Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Dmitry Timoshkov 2020-03-31 19:00:21 +08:00 committed by Alexandre Julliard
parent 6591ddd58c
commit 5a6f56d3a2
3 changed files with 73 additions and 17 deletions

View File

@ -391,7 +391,7 @@ typedef struct
ULONG attrs_count, attrs_count_allocated;
struct ldap_attribute *attrs;
struct attribute_type *at;
ULONG at_count;
ULONG at_single_count, at_multiple_count;
struct
{
ADS_SCOPEENUM scope;
@ -484,7 +484,7 @@ static ULONG WINAPI ldapns_Release(IADs *iface)
SysFreeString(ldap->host);
SysFreeString(ldap->object);
free_attributes(ldap);
free_attribute_types(ldap->at, ldap->at_count);
free_attribute_types(ldap->at, ldap->at_single_count + ldap->at_multiple_count);
heap_free(ldap);
}
@ -943,7 +943,7 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B
IADs *ads;
LDAP *ld = NULL;
HRESULT hr;
ULONG err, at_count = 0;
ULONG err, at_single_count = 0, at_multiple_count = 0;
struct attribute_type *at = NULL;
TRACE("%p,%s,%s,%p,%08x,%p\n", iface, debugstr_w(path), debugstr_w(user), password, flags, obj);
@ -1043,7 +1043,7 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B
}
}
at = load_schema(ld, &at_count);
at = load_schema(ld, &at_single_count, &at_multiple_count);
}
hr = LDAPNamespace_create(&IID_IADs, (void **)&ads);
@ -1055,7 +1055,8 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B
ldap->port = port;
ldap->object = object;
ldap->at = at;
ldap->at_count = at_count;
ldap->at_single_count = at_single_count;
ldap->at_multiple_count = at_multiple_count;
hr = IADs_QueryInterface(ads, &IID_IDispatch, (void **)obj);
IADs_Release(ads);
return hr;
@ -1314,7 +1315,7 @@ static HRESULT add_column_values(LDAP_namespace *ldap, struct ldap_search_contex
ADSTYPEENUM type;
DWORD i, count;
type = get_schema_type(name, ldap->at, ldap->at_count);
type = get_schema_type(name, ldap->at, ldap->at_single_count, ldap->at_multiple_count);
TRACE("%s => type %d\n", debugstr_w(name), type);
switch (type)
@ -1577,7 +1578,8 @@ static HRESULT LDAPNamespace_create(REFIID riid, void **obj)
ldap->attrs = NULL;
ldap->search.scope = ADS_SCOPE_SUBTREE;
ldap->at = NULL;
ldap->at_count = 0;
ldap->at_single_count = 0;
ldap->at_multiple_count = 0;
hr = IADs_QueryInterface(&ldap->IADs_iface, riid, obj);
IADs_Release(&ldap->IADs_iface);

View File

@ -56,8 +56,8 @@ struct attribute_type
};
DWORD map_ldap_error(DWORD) DECLSPEC_HIDDEN;
struct attribute_type *load_schema(LDAP *ld, ULONG *) DECLSPEC_HIDDEN;
ADSTYPEENUM get_schema_type(const WCHAR *, const struct attribute_type *, ULONG) DECLSPEC_HIDDEN;
struct attribute_type *load_schema(LDAP *ld, ULONG *, ULONG *) DECLSPEC_HIDDEN;
ADSTYPEENUM get_schema_type(const WCHAR *, const struct attribute_type *, ULONG, ULONG) DECLSPEC_HIDDEN;
void free_attribute_types(struct attribute_type *, ULONG) DECLSPEC_HIDDEN;
#endif

View File

@ -30,11 +30,41 @@
WINE_DEFAULT_DEBUG_CHANNEL(adsldp);
static const struct attribute_type *find_schema_type(const WCHAR *name, const struct attribute_type *at, ULONG count)
static const struct attribute_type *find_schema_type_sorted(const WCHAR *name, const struct attribute_type *at, ULONG count)
{
int idx, min, max, res;
if (!count) return NULL;
min = 0;
max = count - 1;
while (min <= max)
{
idx = (min + max) / 2;
res = wcsicmp(name, at[idx].name);
if (!res) return &at[idx];
if (res > 0) min = idx + 1;
else max = idx - 1;
}
return NULL;
}
static const struct attribute_type *find_schema_type(const WCHAR *name, const struct attribute_type *at, ULONG single, ULONG multiple)
{
const struct attribute_type *found;
ULONG i, n, off;
for (i = 0; i < count; i++)
/* Perform binary search within definitions with single name */
found = find_schema_type_sorted(name, at, single);
if (found) return found;
/* Perform linear search within definitions with multiple names */
at += single;
for (i = 0; i < multiple; i++)
{
off = 0;
@ -45,15 +75,16 @@ static const struct attribute_type *find_schema_type(const WCHAR *name, const st
}
}
FIXME("%s not found\n", debugstr_w(name));
return NULL;
}
/* RFC 4517 */
ADSTYPEENUM get_schema_type(const WCHAR *name, const struct attribute_type *at, ULONG at_count)
ADSTYPEENUM get_schema_type(const WCHAR *name, const struct attribute_type *at, ULONG single, ULONG multiple)
{
const struct attribute_type *type;
type = find_schema_type(name, at, at_count);
type = find_schema_type(name, at, single, multiple);
if (!type || !type->syntax) return ADSTYPE_CASE_IGNORE_STRING;
if (!wcscmp(type->syntax, L"1.3.6.1.4.1.1466.115.121.1.7"))
@ -300,16 +331,29 @@ static BOOL parse_attribute_type(WCHAR *str, struct attribute_type *at)
return FALSE;
}
struct attribute_type *load_schema(LDAP *ld, ULONG *at_count)
static int __cdecl at_cmp(const void *a1, const void *a2)
{
const struct attribute_type *at1 = a1;
const struct attribute_type *at2 = a2;
if (at1->name_count == 1 && at2->name_count == 1)
return wcsicmp(at1->name, at2->name);
/* put definitions with multiple names at the end */
return at1->name_count - at2->name_count;
}
struct attribute_type *load_schema(LDAP *ld, ULONG *at_single_count, ULONG *at_multiple_count)
{
WCHAR *subschema[] = { (WCHAR *)L"subschemaSubentry", NULL };
WCHAR *attribute_types[] = { (WCHAR *)L"attributeTypes", NULL };
ULONG err, count;
ULONG err, count, multiple_count;
LDAPMessage *res, *entry;
WCHAR **schema = NULL;
struct attribute_type *at = NULL;
*at_count = 0;
*at_single_count = 0;
*at_multiple_count = 0;
err = ldap_search_sW(ld, NULL, LDAP_SCOPE_BASE, (WCHAR *)L"(objectClass=*)", subschema, FALSE, &res);
if (err != LDAP_SUCCESS)
@ -334,6 +378,7 @@ struct attribute_type *load_schema(LDAP *ld, ULONG *at_count)
}
count = 0;
multiple_count = 0;
entry = ldap_first_entry(ld, res);
if (entry)
@ -367,6 +412,9 @@ struct attribute_type *load_schema(LDAP *ld, ULONG *at_count)
TRACE("oid %s, name %s, name_count %u, syntax %s, single-value %d\n", debugstr_w(at[count].oid),
debugstr_w(at[count].name), at[count].name_count, debugstr_w(at[count].syntax), at[count].single_value);
if (at[count].name_count > 1)
multiple_count++;
count++;
}
@ -376,7 +424,13 @@ struct attribute_type *load_schema(LDAP *ld, ULONG *at_count)
exit:
ldap_msgfree(res);
if (at) *at_count = count;
if (at)
{
*at_single_count = count - multiple_count;
*at_multiple_count = multiple_count;
qsort(at, count, sizeof(at[0]), at_cmp);
}
return at;
}