Dmitry Timoshkov : adsldp: Implement IADs::GetInfoEx().

Alexandre Julliard julliard at winehq.org
Tue Mar 24 15:28:15 CDT 2020


Module: wine
Branch: master
Commit: 9c3ca265ad599d7a95dfca07eef31fd8201ab3d7
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=9c3ca265ad599d7a95dfca07eef31fd8201ab3d7

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Mon Mar 23 21:14:46 2020 +0800

adsldp: Implement IADs::GetInfoEx().

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/adsldp/adsldp.c         | 142 ++++++++++++++++++++++++++++++++++++++++++-
 dlls/adsldp/adsldp_private.h |  10 +++
 2 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c
index 58db41a094..942c471dfb 100644
--- a/dlls/adsldp/adsldp.c
+++ b/dlls/adsldp/adsldp.c
@@ -40,7 +40,6 @@
 
 #include "adsldp_private.h"
 
-#include "wine/heap.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(adsldp);
@@ -372,6 +371,12 @@ static HRESULT ADSystemInfo_create(REFIID riid, void **obj)
     return hr;
 }
 
+struct ldap_attribute
+{
+    WCHAR *name;
+    WCHAR **values;
+};
+
 typedef struct
 {
     IADs IADs_iface;
@@ -381,6 +386,8 @@ typedef struct
     BSTR host;
     BSTR object;
     ULONG port;
+    ULONG attrs_count, attrs_count_allocated;
+    struct ldap_attribute *attrs;
 } LDAP_namespace;
 
 static inline LDAP_namespace *impl_from_IADs(IADs *iface)
@@ -422,6 +429,23 @@ static ULONG WINAPI ldapns_AddRef(IADs *iface)
     return InterlockedIncrement(&ldap->ref);
 }
 
+static void free_attributes(LDAP_namespace *ldap)
+{
+    ULONG i;
+
+    if (!ldap->attrs) return;
+
+    for (i = 0; i < ldap->attrs_count; i++)
+    {
+        ldap_memfreeW(ldap->attrs[i].name);
+        ldap_value_freeW(ldap->attrs[i].values);
+    }
+
+    heap_free(ldap->attrs);
+    ldap->attrs = NULL;
+    ldap->attrs_count = 0;
+}
+
 static ULONG WINAPI ldapns_Release(IADs *iface)
 {
     LDAP_namespace *ldap = impl_from_IADs(iface);
@@ -433,6 +457,7 @@ static ULONG WINAPI ldapns_Release(IADs *iface)
         if (ldap->ld) ldap_unbind(ldap->ld);
         SysFreeString(ldap->host);
         SysFreeString(ldap->object);
+        free_attributes(ldap);
         heap_free(ldap);
     }
 
@@ -548,10 +573,118 @@ static HRESULT WINAPI ldapns_PutEx(IADs *iface, LONG code, BSTR name, VARIANT pr
     return E_NOTIMPL;
 }
 
+static HRESULT add_attribute(LDAP_namespace *ldap, WCHAR *name, WCHAR **values)
+{
+    struct ldap_attribute *new_attrs;
+
+    if (!ldap->attrs)
+    {
+        ldap->attrs = heap_alloc(256 * sizeof(ldap->attrs[0]));
+        if (!ldap->attrs) return E_OUTOFMEMORY;
+        ldap->attrs_count_allocated = 256;
+    }
+    else if (ldap->attrs_count_allocated < ldap->attrs_count + 1)
+    {
+        new_attrs = heap_realloc(ldap->attrs, (ldap->attrs_count_allocated * 2) * sizeof(*new_attrs));
+        if (!new_attrs) return E_OUTOFMEMORY;
+
+        ldap->attrs_count_allocated *= 2;
+        ldap->attrs = new_attrs;
+    }
+
+    ldap->attrs[ldap->attrs_count].name = name;
+    ldap->attrs[ldap->attrs_count].values = values;
+    ldap->attrs_count++;
+
+    return S_OK;
+}
+
 static HRESULT WINAPI ldapns_GetInfoEx(IADs *iface, VARIANT prop, LONG reserved)
 {
-    FIXME("%p,%s,%d: stub\n", iface, wine_dbgstr_variant(&prop), reserved);
-    return E_NOTIMPL;
+    LDAP_namespace *ldap = impl_from_IADs(iface);
+    HRESULT hr;
+    SAFEARRAY *sa;
+    VARIANT *item;
+    WCHAR **props = NULL, *attr, **values;
+    DWORD i, count, err;
+    LDAPMessage *res = NULL, *entry;
+    BerElement *ber;
+
+    TRACE("%p,%s,%d\n", iface, wine_dbgstr_variant(&prop), reserved);
+
+    free_attributes(ldap);
+
+    if (!ldap->ld) return E_NOTIMPL;
+
+    if (V_VT(&prop) != (VT_ARRAY | VT_VARIANT))
+        return E_ADS_BAD_PARAMETER;
+
+    sa = V_ARRAY(&prop);
+    if (sa->cDims != 1)
+        return E_ADS_BAD_PARAMETER;
+
+    hr = SafeArrayAccessData(sa, (void *)&item);
+    if (hr != S_OK) return hr;
+
+    count = sa->rgsabound[0].cElements;
+    if (count)
+    {
+        props = heap_alloc((count + 1) * sizeof(props[0]));
+        if (!props)
+        {
+            hr = E_OUTOFMEMORY;
+            goto exit;
+        }
+
+        for (i = 0; i < count; i++)
+        {
+            if (V_VT(&item[i]) != VT_BSTR)
+            {
+                hr = E_ADS_BAD_PARAMETER;
+                goto exit;
+            }
+            props[i] = V_BSTR(&item[i]);
+        }
+        props[sa->rgsabound[0].cElements] = NULL;
+    }
+
+    err = ldap_search_sW(ldap->ld, NULL, LDAP_SCOPE_BASE, (WCHAR *)L"(objectClass=*)", props, FALSE, &res);
+    if (err != LDAP_SUCCESS)
+    {
+        TRACE("ldap_search_sW error %#x\n", err);
+        hr = HRESULT_FROM_WIN32(map_ldap_error(err));
+        goto exit;
+    }
+
+    entry = ldap_first_entry(ldap->ld, res);
+    while (entry)
+    {
+        attr = ldap_first_attributeW(ldap->ld, entry, &ber);
+        while (attr)
+        {
+            TRACE("attr: %s\n", debugstr_w(attr));
+
+            values = ldap_get_valuesW(ldap->ld, entry, attr);
+
+            hr = add_attribute(ldap, attr, values);
+            if (hr != S_OK)
+            {
+                ldap_value_freeW(values);
+                ldap_memfreeW(attr);
+                goto exit;
+            }
+
+            attr = ldap_next_attributeW(ldap->ld, entry, ber);
+        }
+
+        entry = ldap_next_entry(ldap->ld, res);
+    }
+
+exit:
+    if (res) ldap_msgfree(res);
+    heap_free(props);
+    SafeArrayUnaccessData(sa);
+    return hr;
 }
 
 static const IADsVtbl IADs_vtbl =
@@ -867,6 +1000,9 @@ static HRESULT LDAPNamespace_create(REFIID riid, void **obj)
     ldap->ld = NULL;
     ldap->host = NULL;
     ldap->object = NULL;
+    ldap->attrs_count = 0;
+    ldap->attrs_count_allocated = 0;
+    ldap->attrs = NULL;
 
     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 8748d0496d..0443ffbf6e 100644
--- a/dlls/adsldp/adsldp_private.h
+++ b/dlls/adsldp/adsldp_private.h
@@ -19,6 +19,16 @@
 #ifndef _ADSLDP_PRIVATE_H
 #define _ADSLDP_PRIVATE_H
 
+#include "wine/heap.h"
+
+static inline WCHAR *strdupW(const WCHAR *src)
+{
+    WCHAR *dst;
+    if (!src) return NULL;
+    if ((dst = heap_alloc((wcslen(src) + 1) * sizeof(WCHAR)))) wcscpy(dst, src);
+    return dst;
+}
+
 DWORD map_ldap_error(DWORD) DECLSPEC_HIDDEN;
 
 #endif




More information about the wine-cvs mailing list