-- v2: adsldp/tests: Add a test for opening schema as an ADs object. adsldp: Accept virtual objects in IADsOpenDSObject::OpenDSObject(). adsldp/tests: Add some tests for IADs::get_Schema(). activeds: Retry without ADS_SECURE_AUTHENTICATION for an AD path. adsldp: Fail to create IADs if it doesn't have an associated schema attribute. adsldp: Implement IADs::get_Schema().
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/adsldp/adsldp.c | 54 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c index 236a23092c5..2c56349a725 100644 --- a/dlls/adsldp/adsldp.c +++ b/dlls/adsldp/adsldp.c @@ -383,6 +383,7 @@ typedef struct LDAP *ld; BSTR host; BSTR object; + BSTR schema; ULONG port; ULONG attrs_count, attrs_count_allocated; ADS_SEARCH_COLUMN *attrs; @@ -556,8 +557,56 @@ static HRESULT WINAPI ldapns_get_Parent(IADs *iface, BSTR *retval)
static HRESULT WINAPI ldapns_get_Schema(IADs *iface, BSTR *retval) { - FIXME("%p,%p: stub\n", iface, retval); - return E_NOTIMPL; + LDAP_namespace *ldap = impl_from_IADs(iface); + HRESULT hr; + + TRACE("%p,%p\n", iface, retval); + + if (!ldap->schema) + { + VARIANT var, item; + LONG start, end; + + hr = IADs_GetEx(iface, (BSTR)L"objectClass", &var); + if (hr != S_OK) return E_ADS_PROPERTY_NOT_SUPPORTED; + if (V_VT(&var) != (VT_ARRAY | VT_VARIANT)) + { + VariantClear(&var); + return E_ADS_PROPERTY_NOT_SUPPORTED; + } + + SafeArrayGetLBound(V_ARRAY(&var), 1, &start); + SafeArrayGetUBound(V_ARRAY(&var), 1, &end); + VariantInit(&item); + hr = SafeArrayGetElement(V_ARRAY(&var), &start, &item); + if (hr == S_OK) + { + if (V_VT(&item) == VT_BSTR) + { + if (!wcsicmp(V_BSTR(&item), L"top")) + { + VariantClear(&item); + hr = SafeArrayGetElement(V_ARRAY(&var), &end, &item); + if (hr == S_OK) + ldap->schema = SysAllocString(V_BSTR(&item)); + } + else + ldap->schema = SysAllocString(V_BSTR(&item)); + } + + VariantClear(&item); + } + } + + TRACE("ldap->schema: %s\n", debugstr_w(ldap->schema)); + if (!ldap->schema) return E_ADS_PROPERTY_NOT_SUPPORTED; + + *retval = SysAllocStringLen(NULL, wcslen(ldap->schema) + sizeof(L"LDAP://schema/") / sizeof(WCHAR)); + if (!*retval) return E_OUTOFMEMORY; + + wcscpy(*retval, L"LDAP://schema/"); + wcscat(*retval, ldap->schema); + return S_OK; }
static HRESULT WINAPI ldapns_GetInfo(IADs *iface) @@ -2102,6 +2151,7 @@ static HRESULT LDAPNamespace_create(REFIID riid, void **obj) ldap->ld = NULL; ldap->host = NULL; ldap->object = NULL; + ldap->schema = NULL; ldap->attrs_count = 0; ldap->attrs_count_allocated = 0; ldap->attrs = NULL;
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/adsldp/adsldp.c | 17 +++++++++++++++++ dlls/adsldp/tests/ldap.c | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c index 2c56349a725..e9b9b70c2a8 100644 --- a/dlls/adsldp/adsldp.c +++ b/dlls/adsldp/adsldp.c @@ -1231,6 +1231,7 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B if (hr == S_OK) { LDAP_namespace *ldap = impl_from_IADs(ads); + ldap->ld = ld; ldap->host = host; ldap->port = port; @@ -1238,8 +1239,24 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B ldap->at = at; ldap->at_single_count = at_single_count; ldap->at_multiple_count = at_multiple_count; + + /* Windows fails to create IADs if it doesn't have an associated schema attribute */ + if (object && wcsicmp(object, L"rootDSE") != 0) + { + BSTR schema; + + if (IADs_get_Schema(ads, &schema) != S_OK) + { + IADs_Release(ads); + return E_ADS_BAD_PATHNAME; + } + + SysFreeString(schema); + } + hr = IADs_QueryInterface(ads, &IID_IDispatch, (void **)obj); IADs_Release(ads); + return hr; }
diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c index af965000e26..19e1f94d73e 100644 --- a/dlls/adsldp/tests/ldap.c +++ b/dlls/adsldp/tests/ldap.c @@ -207,7 +207,7 @@ static void test_ParseDisplayName(void) server_down = TRUE; break; } - todo_wine_if(i == 0 || i == 1 || i == 11 || i == 12) + todo_wine_if(i == 0 || i == 1) ok(hr == test[i].hr, "%d: got %#lx, expected %#lx\n", i, hr, test[i].hr); if (hr == S_OK) {
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/activeds/activeds_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/activeds/activeds_main.c b/dlls/activeds/activeds_main.c index 246d2f39628..1f59d1aa458 100644 --- a/dlls/activeds/activeds_main.c +++ b/dlls/activeds/activeds_main.c @@ -47,8 +47,10 @@ HRESULT WINAPI ADsGetObject(LPCWSTR path, REFIID riid, void **obj) { HRESULT hr;
+ TRACE("(%s, %s, %p)\n", debugstr_w(path), wine_dbgstr_guid(riid), obj); + hr = ADsOpenObject(path, NULL, NULL, ADS_SECURE_AUTHENTICATION, riid, obj); - if (hr != S_OK) + if (hr != S_OK && hr != E_ADS_BAD_PATHNAME) hr = ADsOpenObject(path, NULL, NULL, 0, riid, obj); return hr; }
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/adsldp/tests/ldap.c | 118 +++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 41 deletions(-)
diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c index 19e1f94d73e..f7b34e83021 100644 --- a/dlls/adsldp/tests/ldap.c +++ b/dlls/adsldp/tests/ldap.c @@ -598,10 +598,43 @@ static void test_DirectoryObject(void) IDirectoryObject_Release(dirobj); }
+static void get_attribute(IADs *ads, BSTR name, int vt) +{ + HRESULT hr; + VARIANT var; + + VariantInit(&var); + hr = IADs_GetEx(ads, name, &var); + ok(hr == S_OK, "GetEx(%s) error %#lx\n", wine_dbgstr_w(name), hr); + ok(V_VT(&var) == vt, "attribute %s has vt %#x\n", wine_dbgstr_w(name), V_VT(&var)); + if (V_VT(&var) != vt) return; + + if (V_VT(&var) | VT_ARRAY) + { + VARIANT item; + LONG start, end, idx; + + hr = SafeArrayGetLBound(V_ARRAY(&var), 1, &start); + ok(hr == S_OK, "got %#lx\n", hr); + hr = SafeArrayGetUBound(V_ARRAY(&var), 1, &end); + ok(hr == S_OK, "got %#lx\n", hr); + for (idx = start; idx <= end; idx++) + { + VariantInit(&item); + hr = SafeArrayGetElement(V_ARRAY(&var), &idx, &item); + ok(hr == S_OK, "got %#lx\n", hr); + ok(V_VT(&item) == VT_BSTR, "%ld: got %d\n", idx, V_VT(&item)); + trace("%s[%ld]: %s\n", wine_dbgstr_w(name), idx, wine_dbgstr_w(V_BSTR(&item))); + VariantClear(&item); + } + } + VariantClear(&var); +} + static void test_IADs_GetEx(void) { HRESULT hr; - IADs *ads; + IADs *ads, *ads2; BSTR bstr; VARIANT var, item, bin; LONG start, end, idx, found; @@ -615,42 +648,26 @@ static void test_IADs_GetEx(void) return; }
+ hr = IADs_get_Schema(ads, &bstr); + ok(hr == E_ADS_PROPERTY_NOT_SUPPORTED, "got %#lx\n", hr); + VariantInit(&var); - bstr = SysAllocString(L"defaultNamingContext"); - hr = IADs_Get(ads, bstr, &var); - SysFreeString(bstr); + hr = IADs_Get(ads, (BSTR)L"objectClass", &var); + ok(hr == E_ADS_PROPERTY_NOT_FOUND, "got %#lx\n", hr); + + VariantInit(&var); + hr = IADs_Get(ads, (BSTR)L"defaultNamingContext", &var); ok(hr == S_OK, "got %#lx\n", hr); ok(V_VT(&var) == VT_BSTR, "got %#x\n", V_VT(&var)); - trace("VT_BSTR => %s\n", wine_dbgstr_w(V_BSTR(&var))); + trace("defaultNamingContext: %s\n", wine_dbgstr_w(V_BSTR(&var))); wcscpy(path, L"LDAP://"); wcscat(path, V_BSTR(&var)); VariantClear(&var);
- VariantInit(&var); - bstr = SysAllocString(L"defaultNamingContext"); - hr = IADs_GetEx(ads, bstr, &var); - SysFreeString(bstr); - ok(hr == S_OK, "got %#lx\n", hr); - ok(V_VT(&var) == (VT_ARRAY | VT_VARIANT), "got %#x\n", V_VT(&var)); - hr = SafeArrayGetLBound(V_ARRAY(&var), 1, &start); - ok(hr == S_OK, "got %#lx\n", hr); - hr = SafeArrayGetUBound(V_ARRAY(&var), 1, &end); - ok(hr == S_OK, "got %#lx\n", hr); - VariantInit(&item); - for (idx = start; idx <= end; idx++) - { - hr = SafeArrayGetElement(V_ARRAY(&var), &idx, &item); - ok(hr == S_OK, "got %#lx\n", hr); - ok(V_VT(&item) == VT_BSTR, "%ld: got %d\n", idx, V_VT(&item)); - trace("%ld: VT_BSTR => %s\n", idx, wine_dbgstr_w(V_BSTR(&item))); - VariantClear(&item); - } - VariantClear(&var); + get_attribute(ads, (BSTR)L"defaultNamingContext", VT_ARRAY | VT_VARIANT);
VariantInit(&var); - bstr = SysAllocString(L"wellKnownObjects"); - hr = IADs_Get(ads, bstr, &var); - SysFreeString(bstr); + hr = IADs_Get(ads, (BSTR)L"wellKnownObjects", &var); ok(hr == E_ADS_PROPERTY_NOT_FOUND, "got %#lx\n", hr);
IADs_Release(ads); @@ -658,11 +675,16 @@ static void test_IADs_GetEx(void) hr = ADsGetObject(path, &IID_IADs, (void **)&ads); ok(hr == S_OK, "got %#lx\n", hr);
+ get_attribute(ads, (BSTR)L"objectClass", VT_ARRAY | VT_VARIANT); + + hr = IADs_get_Schema(ads, &bstr); + ok(hr == S_OK, "got %#lx\n", hr); + trace("Schema of %s: %s\n", wine_dbgstr_w(path), wine_dbgstr_w(bstr)); + SysFreeString(bstr); + /* ::Get() */ VariantInit(&var); - bstr = SysAllocString(L"wellKnownObjects"); - hr = IADs_Get(ads, bstr, &var); - SysFreeString(bstr); + hr = IADs_Get(ads, (BSTR)L"wellKnownObjects", &var); ok(hr == S_OK, "got %#lx\n", hr); ok(V_VT(&var) == (VT_ARRAY | VT_VARIANT), "got %#x\n", V_VT(&var)); hr = SafeArrayGetLBound(V_ARRAY(&var), 1, &start); @@ -681,6 +703,10 @@ static void test_IADs_GetEx(void) hr = IDispatch_QueryInterface(V_DISPATCH(&item), &IID_IADsDNWithBinary, (void **)&dn); ok(hr == S_OK, "IID_IADsDNWithBinary: got %#lx\n", hr);
+ hr = IADsDNWithBinary_get_DNString(dn, &bstr); + ok(hr == S_OK, "got %#lx\n", hr); + trace("%ld: DNString => %s\n", idx, wine_dbgstr_w(bstr)); + VariantInit(&bin); hr = IADsDNWithBinary_get_BinaryValue(dn, &bin); ok(hr == S_OK, "got %#lx\n", hr); @@ -694,10 +720,6 @@ static void test_IADs_GetEx(void) !memcmp(V_ARRAY(&bin)->pvData, &CLSID_Users, sizeof(CLSID))) found++;
- hr = IADsDNWithBinary_get_DNString(dn, &bstr); - ok(hr == S_OK, "got %#lx\n", hr); - trace("%ld: DNString => %s\n", idx, wine_dbgstr_w(bstr)); - IADsDNWithBinary_Release(dn); VariantClear(&item); } @@ -706,9 +728,7 @@ static void test_IADs_GetEx(void)
/* ::GetEx() */ VariantInit(&var); - bstr = SysAllocString(L"wellKnownObjects"); - hr = IADs_GetEx(ads, bstr, &var); - SysFreeString(bstr); + hr = IADs_GetEx(ads, (BSTR)L"wellKnownObjects", &var); ok(hr == S_OK, "got %#lx\n", hr); ok(V_VT(&var) == (VT_ARRAY | VT_VARIANT), "got %#x\n", V_VT(&var)); hr = SafeArrayGetLBound(V_ARRAY(&var), 1, &start); @@ -726,6 +746,10 @@ static void test_IADs_GetEx(void) hr = IDispatch_QueryInterface(V_DISPATCH(&item), &IID_IADsDNWithBinary, (void **)&dn); ok(hr == S_OK, "IID_IADsDNWithBinary: got %#lx\n", hr);
+ hr = IADsDNWithBinary_get_DNString(dn, &bstr); + ok(hr == S_OK, "got %#lx\n", hr); + trace("%ld: DNString => %s\n", idx, wine_dbgstr_w(bstr)); + VariantInit(&bin); hr = IADsDNWithBinary_get_BinaryValue(dn, &bin); ok(hr == S_OK, "got %#lx\n", hr); @@ -739,9 +763,21 @@ static void test_IADs_GetEx(void) !memcmp(V_ARRAY(&bin)->pvData, &CLSID_Users, sizeof(CLSID))) found++;
- hr = IADsDNWithBinary_get_DNString(dn, &bstr); - ok(hr == S_OK, "got %#lx\n", hr); - trace("%ld: DNString => %s\n", idx, wine_dbgstr_w(bstr)); + wcscpy(path, L"LDAP://"); + wcscat(path, bstr); + SysFreeString(bstr); + hr = ADsOpenObject(path, NULL, NULL, ADS_SECURE_AUTHENTICATION, &IID_IADs, (void **)&ads2); + if (hr == S_OK) + { + get_attribute(ads2, (BSTR)L"objectClass", VT_ARRAY | VT_VARIANT); + + hr = IADs_get_Schema(ads2, &bstr); + ok(hr == S_OK, "got %#lx\n", hr); + trace("Schema of %s: %s\n", wine_dbgstr_w(path), wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + IADs_Release(ads2); + }
VariantClear(&bin); IADsDNWithBinary_Release(dn);
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/adsldp/Makefile.in | 2 +- dlls/adsldp/adsldp.c | 172 +++++++++++++++++++++++----------------- 2 files changed, 99 insertions(+), 75 deletions(-)
diff --git a/dlls/adsldp/Makefile.in b/dlls/adsldp/Makefile.in index 4031656a5b4..3db03d4596b 100644 --- a/dlls/adsldp/Makefile.in +++ b/dlls/adsldp/Makefile.in @@ -1,6 +1,6 @@ MODULE = adsldp.dll IMPORTS = ole32 oleaut32 secur32 activeds uuid -DELAYIMPORTS = netapi32 wldap32 +DELAYIMPORTS = wldap32
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c index e9b9b70c2a8..5c59cef05e5 100644 --- a/dlls/adsldp/adsldp.c +++ b/dlls/adsldp/adsldp.c @@ -1116,6 +1116,77 @@ static HRESULT parse_path(WCHAR *path, BSTR *host, ULONG *port, BSTR *object) return S_OK; }
+static HRESULT bind_to_host(BSTR host, ULONG port, LONG flags, BSTR user, BSTR password, LDAP **ld_ret) +{ + LDAP *ld; + ULONG err; + int version; + HRESULT hr; + + TRACE("binding to host %s, port %lu\n", debugstr_w(host), port); + + ld = ldap_initW(host, port); + if (!ld) + { + hr = HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN); + goto fail; + } + + version = LDAP_VERSION3; + err = ldap_set_optionW(ld, LDAP_OPT_PROTOCOL_VERSION, &version); + if (err != LDAP_SUCCESS) + { + hr = HRESULT_FROM_WIN32(map_ldap_error(err)); + goto fail; + } + + err = ldap_connect(ld, NULL); + if (err != LDAP_SUCCESS) + { + hr = HRESULT_FROM_WIN32(map_ldap_error(err)); + goto fail; + } + + if (flags & ADS_SECURE_AUTHENTICATION) + { + SEC_WINNT_AUTH_IDENTITY_W id; + + id.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + id.Domain = (unsigned short *)host; + id.DomainLength = host ? wcslen(host) : 0; + id.User = (unsigned short *)user; + id.UserLength = user ? wcslen(user) : 0; + id.Password = (unsigned short *)password; + id.PasswordLength = password ? wcslen(password) : 0; + + err = ldap_bind_sW(ld, NULL, (WCHAR *)&id, LDAP_AUTH_NEGOTIATE); + if (err != LDAP_SUCCESS) + { + TRACE("ldap_bind_sW error %#lx\n", err); + hr = HRESULT_FROM_WIN32(map_ldap_error(err)); + goto fail; + } + } + else + { + err = ldap_simple_bind_sW(ld, user, password); + if (err != LDAP_SUCCESS) + { + TRACE("ldap_simple_bind_sW error %#lx\n", err); + hr = HRESULT_FROM_WIN32(map_ldap_error(err)); + goto fail; + } + } + + *ld_ret = ld; + return S_OK; + +fail: + ldap_unbind(ld); + *ld_ret = NULL; + return hr; +} + static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, BSTR user, BSTR password, LONG flags, IDispatch **obj) { @@ -1124,7 +1195,7 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B IADs *ads; LDAP *ld = NULL; HRESULT hr; - ULONG err, at_single_count = 0, at_multiple_count = 0; + ULONG at_single_count = 0, at_multiple_count = 0; struct attribute_type *at = NULL;
TRACE("%p,%s,%s,%p,%08lx,%p\n", iface, debugstr_w(path), debugstr_w(user), password, flags, obj); @@ -1136,12 +1207,8 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B
if (host) { - int version; - if (!wcsicmp(host, L"rootDSE")) { - DOMAIN_CONTROLLER_INFOW *dcinfo; - if (object) { hr = E_ADS_BAD_PATHNAME; @@ -1149,81 +1216,33 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B }
object = host; - - err = DsGetDcNameW(NULL, NULL, NULL, NULL, DS_RETURN_DNS_NAME, &dcinfo); - if (err != ERROR_SUCCESS) - { - hr = HRESULT_FROM_WIN32(err); - goto fail; - } - - host = SysAllocString(dcinfo->DomainName); - NetApiBufferFree(dcinfo); - - if (!host) - { - hr = E_OUTOFMEMORY; - goto fail; - } - } - - ld = ldap_initW(host, port); - if (!ld) - { - hr = HRESULT_FROM_WIN32(LdapGetLastError()); - goto fail; - } - - version = LDAP_VERSION3; - err = ldap_set_optionW(ld, LDAP_OPT_PROTOCOL_VERSION, &version); - if (err != LDAP_SUCCESS) - { - hr = HRESULT_FROM_WIN32(map_ldap_error(err)); - ldap_unbind(ld); - goto fail; - } - - err = ldap_connect(ld, NULL); - if (err != LDAP_SUCCESS) - { - hr = HRESULT_FROM_WIN32(map_ldap_error(err)); - ldap_unbind(ld); - goto fail; + host = NULL; }
- if (flags & ADS_SECURE_AUTHENTICATION) + hr = bind_to_host(host, port, flags, user, password, &ld); + if (hr != S_OK && host) { - SEC_WINNT_AUTH_IDENTITY_W id; - - id.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - id.Domain = (unsigned short *)host; - id.DomainLength = wcslen(host); - id.User = (unsigned short *)user; - id.UserLength = user ? wcslen(user) : 0; - id.Password = (unsigned short *)password; - id.PasswordLength = password ? wcslen(password) : 0; + if (hr != HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN)) goto fail;
- err = ldap_bind_sW(ld, NULL, (WCHAR *)&id, LDAP_AUTH_NEGOTIATE); - if (err != LDAP_SUCCESS) + SysFreeString(host); + if (!object) { - TRACE("ldap_bind_sW error %#lx\n", err); - hr = HRESULT_FROM_WIN32(map_ldap_error(err)); - ldap_unbind(ld); - goto fail; + host = NULL; + object = SysAllocString(path + 7); /* skip LDAP:// */ + + TRACE("retrying with host %s, port %lu, object %s\n", debugstr_w(host), port, debugstr_w(object)); + hr = bind_to_host(host, port, flags, user, password, &ld); } - } - else - { - err = ldap_simple_bind_sW(ld, user, password); - if (err != LDAP_SUCCESS) + else { - TRACE("ldap_simple_bind_sW error %#lx\n", err); - hr = HRESULT_FROM_WIN32(map_ldap_error(err)); - ldap_unbind(ld); - goto fail; + SysFreeString(object); + object = SysAllocString(path + 7); /* skip LDAP:// */ + TRACE("Assume that %s is virtual object\n", debugstr_w(object)); + hr = S_OK; } }
+ if (hr != S_OK) goto fail; at = load_schema(ld, &at_single_count, &at_multiple_count); }
@@ -1241,7 +1260,7 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B ldap->at_multiple_count = at_multiple_count;
/* Windows fails to create IADs if it doesn't have an associated schema attribute */ - if (object && wcsicmp(object, L"rootDSE") != 0) + if (ld && object && wcsicmp(object, L"rootDSE") != 0) { BSTR schema;
@@ -1982,7 +2001,9 @@ static HRESULT WINAPI search_GetColumn(IDirectorySearch *iface, ADS_SEARCH_HANDL goto exit; }
- count = sizeof(L"LDAP://") + (wcslen(ldap->host) + 1 /* '/' */) * sizeof(WCHAR); + count = sizeof(L"LDAP://"); + if (ldap->host) + count += (wcslen(ldap->host) + 1 /* '/' */) * sizeof(WCHAR); if (dn) count += wcslen(dn) * sizeof(WCHAR);
col->pADsValues[0].CaseIgnoreString = malloc(count); @@ -1993,8 +2014,11 @@ static HRESULT WINAPI search_GetColumn(IDirectorySearch *iface, ADS_SEARCH_HANDL }
wcscpy(col->pADsValues[0].CaseIgnoreString, L"LDAP://"); - wcscat(col->pADsValues[0].CaseIgnoreString, ldap->host); - wcscat(col->pADsValues[0].CaseIgnoreString, L"/"); + if (ldap->host) + { + wcscat(col->pADsValues[0].CaseIgnoreString, ldap->host); + wcscat(col->pADsValues[0].CaseIgnoreString, L"/"); + } if (dn) wcscat(col->pADsValues[0].CaseIgnoreString, dn); col->pADsValues[0].dwType = ADSTYPE_CASE_IGNORE_STRING; col->dwADsType = ADSTYPE_CASE_IGNORE_STRING;
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/adsldp/tests/ldap.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c index f7b34e83021..a779868b6ab 100644 --- a/dlls/adsldp/tests/ldap.c +++ b/dlls/adsldp/tests/ldap.c @@ -774,10 +774,17 @@ static void test_IADs_GetEx(void) hr = IADs_get_Schema(ads2, &bstr); ok(hr == S_OK, "got %#lx\n", hr); trace("Schema of %s: %s\n", wine_dbgstr_w(path), wine_dbgstr_w(bstr)); - SysFreeString(bstr);
IADs_Release(ads2); + + hr = ADsOpenObject(bstr, NULL, NULL, ADS_SECURE_AUTHENTICATION, &IID_IADs, (void **)&ads2); + ok(hr == S_OK, "got %#lx\n", hr); + IADs_Release(ads2); + + SysFreeString(bstr); } + else + trace("ADsOpenObject(%s) error %#lx\n", wine_dbgstr_w(path), hr);
VariantClear(&bin); IADsDNWithBinary_Release(dn);
v2: Fix test failures.