Dmitry Timoshkov : adsldp: Sort the attribute types array.
Alexandre Julliard
julliard at winehq.org
Tue Mar 31 16:44:24 CDT 2020
Module: wine
Branch: master
Commit: 5a6f56d3a2e23aebf02c01e547e334dc3fe59f97
URL: https://source.winehq.org/git/wine.git/?a=commit;h=5a6f56d3a2e23aebf02c01e547e334dc3fe59f97
Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date: Tue Mar 31 19:00:21 2020 +0800
adsldp: Sort the attribute types array.
Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/adsldp/adsldp.c | 16 +++++-----
dlls/adsldp/adsldp_private.h | 4 +--
dlls/adsldp/schema.c | 70 +++++++++++++++++++++++++++++++++++++++-----
3 files changed, 73 insertions(+), 17 deletions(-)
diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c
index 8621836afc..c4557667cc 100644
--- a/dlls/adsldp/adsldp.c
+++ b/dlls/adsldp/adsldp.c
@@ -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);
diff --git a/dlls/adsldp/adsldp_private.h b/dlls/adsldp/adsldp_private.h
index a0d3a977a2..ea3d247dee 100644
--- a/dlls/adsldp/adsldp_private.h
+++ b/dlls/adsldp/adsldp_private.h
@@ -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
diff --git a/dlls/adsldp/schema.c b/dlls/adsldp/schema.c
index e91f817fc9..101a84c196 100644
--- a/dlls/adsldp/schema.c
+++ b/dlls/adsldp/schema.c
@@ -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;
}
More information about the wine-cvs
mailing list