diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c index b2a8e61815f..9a52d785005 100644 --- a/dlls/adsldp/adsldp.c +++ b/dlls/adsldp/adsldp.c @@ -45,6 +45,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(adsldp); +#ifndef LDAP_OPT_SERVER_CONTROLS +#define LDAP_OPT_SERVER_CONTROLS 0x0012 +#endif + DEFINE_GUID(CLSID_LDAP,0x228d9a81,0xc302,0x11cf,0x9a,0xa4,0x00,0xaa,0x00,0x4a,0x56,0x91); DEFINE_GUID(CLSID_LDAPNamespace,0x228d9a82,0xc302,0x11cf,0x9a,0xa4,0x00,0xaa,0x00,0x4a,0x56,0x91); @@ -1127,6 +1131,7 @@ static ULONG WINAPI search_Release(IDirectorySearch *iface) static HRESULT WINAPI search_SetSearchPreference(IDirectorySearch *iface, PADS_SEARCHPREF_INFO prefs, DWORD count) { LDAP_namespace *ldap = impl_from_IDirectorySearch(iface); + HRESULT hr = S_OK; DWORD i; TRACE("%p,%p,%u\n", iface, prefs, count); @@ -1159,6 +1164,56 @@ static HRESULT WINAPI search_SetSearchPreference(IDirectorySearch *iface, PADS_S } break; + case ADS_SEARCHPREF_SECURITY_MASK: + { + int security_mask; + ULONG err; + BerElement *ber; + struct berval *berval; + LDAPControlW *ctrls[2], mask; + + if (prefs[i].vValue.dwType != ADSTYPE_INTEGER) + { + FIXME("ADS_SEARCHPREF_SECURITY_MASK: not supportd dwType %d\n", prefs[i].vValue.dwType); + prefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE; + break; + } + + TRACE("SECURITY_MASK: %08x\n", prefs[i].vValue.u.Integer); + security_mask = prefs[i].vValue.u.Integer; + if (!security_mask) + security_mask = ADS_SECURITY_INFO_OWNER; + + ber = ber_alloc_t(LBER_USE_DER); + if (!ber || ber_printf(ber, (char *)"{i}", security_mask) == -1 || ber_flatten(ber, &berval) == -1) + { + ber_free(ber, 1); + prefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREF; + break; + } + TRACE("ber: %s\n", debugstr_an(berval->bv_val, berval->bv_len)); + + mask.ldctl_oid = (WCHAR *)L"1.2.840.113556.1.4.801"; + mask.ldctl_iscritical = TRUE; + mask.ldctl_value.bv_val = berval->bv_val; + mask.ldctl_value.bv_len = berval->bv_len; + ctrls[0] = &mask; + ctrls[1] = NULL; + err = ldap_set_optionW(ldap->ld, LDAP_OPT_SERVER_CONTROLS, ctrls); + if (err != LDAP_SUCCESS) + { + TRACE("ldap_set_option error %#x\n", err); + prefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREF; + hr = S_ADS_ERRORSOCCURRED; + } + else + prefs[i].dwStatus = ADS_STATUS_S_OK; + + ber_bvfree(berval); + ber_free(ber, 1); + break; + } + default: FIXME("pref %d, type %u: stub\n", prefs[i].dwSearchPref, prefs[i].vValue.dwType); prefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREF; @@ -1166,7 +1221,7 @@ static HRESULT WINAPI search_SetSearchPreference(IDirectorySearch *iface, PADS_S } } - return S_OK; + return hr; } static HRESULT WINAPI search_ExecuteSearch(IDirectorySearch *iface, LPWSTR filter, LPWSTR *names, diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c index 998581e2f88..80815b07a0c 100644 --- a/dlls/adsldp/tests/ldap.c +++ b/dlls/adsldp/tests/ldap.c @@ -465,6 +465,9 @@ static void test_DirectoryObject(void) IDirectoryObject *dirobj; IUnknown *unk; IDirectorySearch *ds; + ADS_SEARCHPREF_INFO pref[2]; + ADS_SEARCH_HANDLE sh; + ADS_SEARCH_COLUMN col; hr = ADsGetObject(L"LDAP://ldap.forumsys.com/OU=scientists,DC=example,DC=com", &IID_IDirectoryObject, (void **)&dirobj); if (hr == HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN)) @@ -485,8 +488,39 @@ todo_wine IUnknown_Release(unk); hr = IDirectoryObject_QueryInterface(dirobj, &IID_IDirectorySearch, (void **)&ds); ok(hr == S_OK, "got %#x\n", hr); - IDirectorySearch_Release(ds); + pref[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; + pref[0].vValue.dwType = ADSTYPE_INTEGER; + pref[0].vValue.Integer = ADS_SCOPE_BASE; + pref[0].dwStatus = 0xdeadbeef; + pref[1].dwSearchPref = ADS_SEARCHPREF_SECURITY_MASK; + pref[1].vValue.dwType = ADSTYPE_INTEGER; + pref[1].vValue.Integer = ADS_SECURITY_INFO_OWNER | ADS_SECURITY_INFO_GROUP | ADS_SECURITY_INFO_DACL; + pref[1].dwStatus = 0xdeadbeef; + hr = IDirectorySearch_SetSearchPreference(ds, pref, ARRAY_SIZE(pref)); +todo_wine + ok(hr == S_ADS_ERRORSOCCURRED, "got %#x\n", hr); + ok(pref[0].dwStatus == ADS_STATUS_S_OK, "got %d\n", pref[0].dwStatus); + /* ldap.forumsys.com doesn't support NT security, real ADs DC - does */ +todo_wine + ok(pref[1].dwStatus == ADS_STATUS_INVALID_SEARCHPREF, "got %d\n", pref[1].dwStatus); + + hr = IDirectorySearch_ExecuteSearch(ds, (WCHAR *)L"(objectClass=*)", NULL, ~0, &sh); +todo_wine + ok(hr == S_OK, "got %#x\n", hr); + if (hr != S_OK) goto fail; + + hr = IDirectorySearch_GetNextRow(ds, sh); + ok(hr == S_OK, "got %#x\n", hr); + + hr = IDirectorySearch_GetColumn(ds, sh, (WCHAR *)L"nTSecurityDescriptor", &col); + ok(hr == E_ADS_COLUMN_NOT_SET, "got %#x\n", hr); + + hr = IDirectorySearch_CloseSearchHandle(ds, sh); + ok(hr == S_OK, "got %#x\n", hr); + + IDirectorySearch_Release(ds); +fail: IDirectoryObject_Release(dirobj); } diff --git a/include/iads.idl b/include/iads.idl index b04ed0846a3..e9eaab77bea 100644 --- a/include/iads.idl +++ b/include/iads.idl @@ -362,6 +362,14 @@ typedef struct _ads_attr_info DWORD dwNumValues; } ADS_ATTR_INFO, *PADS_ATTR_INFO; +typedef enum +{ + ADS_SECURITY_INFO_OWNER = 0x1, + ADS_SECURITY_INFO_GROUP = 0x2, + ADS_SECURITY_INFO_DACL = 0x4, + ADS_SECURITY_INFO_SACL = 0x8 +} ADS_SECURITY_INFO_ENUM; + /***************************************************************************** * IADsContainer interface */ diff --git a/include/winldap.h b/include/winldap.h index bd5acab7675..2d41eaa3fa2 100644 --- a/include/winldap.h +++ b/include/winldap.h @@ -104,6 +104,8 @@ typedef enum { #define LDAP_SCOPE_ONELEVEL 0x01 #define LDAP_SCOPE_SUBTREE 0x02 +#define LBER_USE_DER 0x01 + typedef struct berelement { PCHAR opaque;