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