[PATCH 0/1] MR10609: adsldp: Add support for ADS_OPTION_REFERRALS.
From: Dmitry Timoshkov <dmitry@baikal.ru> Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru> --- dlls/adsldp/adsldp.c | 56 ++++++++++++++++++++++++++++++++++++++++++-- include/iads.idl | 8 +++++++ include/winldap.h | 3 +++ 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c index 675ca83d03f..b1e974c1033 100644 --- a/dlls/adsldp/adsldp.c +++ b/dlls/adsldp/adsldp.c @@ -2280,6 +2280,20 @@ static HRESULT WINAPI options_GetOption(IADsObjectOptions *iface, LONG option, V return S_OK; } + case ADS_OPTION_REFERRALS: + { + ULONG val; + + err = ldap_get_optionW(ldap->ld, LDAP_OPT_REFERRALS, &val); + if (err != LDAP_SUCCESS) + return HRESULT_FROM_WIN32(map_ldap_error(err)); + + V_VT(var) = VT_I4; + /* LDAP values are equal to ADS_CHASE_REFERRALS_ constants. */ + V_I4(var) = val; + return S_OK; + } + case ADS_OPTION_ACCUMULATIVE_MODIFICATION: V_VT(var) = VT_BOOL; V_BOOL(var) = VARIANT_FALSE; @@ -2295,18 +2309,56 @@ static HRESULT WINAPI options_GetOption(IADsObjectOptions *iface, LONG option, V static HRESULT WINAPI options_SetOption(IADsObjectOptions *iface, LONG option, VARIANT var) { - FIXME("%p,%ld,%s: stub\n", iface, option, wine_dbgstr_variant(&var)); + LDAP_namespace *ldap = impl_from_IADsObjectOptions(iface); + LONG err; + + TRACE("%p,%ld,%s\n", iface, option, wine_dbgstr_variant(&var)); + + if (!ldap->ld) return E_NOTIMPL; switch (option) { + case ADS_OPTION_REFERRALS: + { + ULONG val; + + if (V_VT(&var) != VT_I4) + return E_ADS_BAD_PARAMETER; + + switch (V_I4(&var)) + { + case ADS_CHASE_REFERRALS_NEVER: + val = 0; + break; + case ADS_CHASE_REFERRALS_SUBORDINATE: + val = LDAP_CHASE_SUBORDINATE_REFERRALS; + break; + case ADS_CHASE_REFERRALS_EXTERNAL: + val = LDAP_CHASE_EXTERNAL_REFERRALS; + break; + case ADS_CHASE_REFERRALS_ALWAYS: + val = LDAP_CHASE_SUBORDINATE_REFERRALS | LDAP_CHASE_EXTERNAL_REFERRALS; + break; + default: + return E_ADS_BAD_PARAMETER; + } + + err = ldap_set_optionW(ldap->ld, LDAP_OPT_REFERRALS, &val); + if (err != LDAP_SUCCESS) + return HRESULT_FROM_WIN32(map_ldap_error(err)); + + return S_OK; + } + case ADS_OPTION_ACCUMULATIVE_MODIFICATION: return S_OK; default: + FIXME("%p,%ld,%s: stub\n", iface, option, wine_dbgstr_variant(&var)); break; } - return E_NOTIMPL; + return E_ADS_BAD_PARAMETER; } static const IADsObjectOptionsVtbl IADsObjectOptions_vtbl = diff --git a/include/iads.idl b/include/iads.idl index c6c72a28761..a6733ed1570 100644 --- a/include/iads.idl +++ b/include/iads.idl @@ -99,6 +99,14 @@ typedef enum ADS_SEARCHPREF_EXTENDED_DN } ADS_SEARCHPREF_ENUM; +typedef enum +{ + ADS_CHASE_REFERRALS_NEVER, + ADS_CHASE_REFERRALS_SUBORDINATE = 0x20, + ADS_CHASE_REFERRALS_EXTERNAL = 0x40, + ADS_CHASE_REFERRALS_ALWAYS = ADS_CHASE_REFERRALS_SUBORDINATE | ADS_CHASE_REFERRALS_EXTERNAL +} ADS_CHASE_REFERRALS_ENUM; + typedef enum { ADS_STATUS_S_OK, diff --git a/include/winldap.h b/include/winldap.h index 4f2543a05aa..8ac6b26e6cb 100644 --- a/include/winldap.h +++ b/include/winldap.h @@ -164,6 +164,9 @@ typedef struct berelement #define LDAP_OPT_ON ((void *)1) #define LDAP_OPT_OFF ((void *)0) +#define LDAP_CHASE_SUBORDINATE_REFERRALS 0x20 +#define LDAP_CHASE_EXTERNAL_REFERRALS 0x40 + #define LDAP_VERSION1 1 #define LDAP_VERSION2 2 #define LDAP_VERSION3 3 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10609
Alexandre Julliard (@julliard) commented about dlls/adsldp/adsldp.c:
+ { + case ADS_CHASE_REFERRALS_NEVER: + val = 0; + break; + case ADS_CHASE_REFERRALS_SUBORDINATE: + val = LDAP_CHASE_SUBORDINATE_REFERRALS; + break; + case ADS_CHASE_REFERRALS_EXTERNAL: + val = LDAP_CHASE_EXTERNAL_REFERRALS; + break; + case ADS_CHASE_REFERRALS_ALWAYS: + val = LDAP_CHASE_SUBORDINATE_REFERRALS | LDAP_CHASE_EXTERNAL_REFERRALS; + break; + default: + return E_ADS_BAD_PARAMETER; + } That switch doesn't seem very useful since we are already assuming that the values are the same.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10609#note_139567
On Tue May 12 11:49:48 2026 +0000, Alexandre Julliard wrote:
That switch doesn't seem very useful since we are already assuming that the values are the same. We don't need to verify the value from LDAP, however SetOption() needs to verify that the value passed by an application is valid.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10609#note_139568
On Tue May 12 11:56:59 2026 +0000, Dmitry Timoshkov wrote:
We don't need to verify the value from LDAP, however SetOption() needs to verify that the value passed by an application is valid. Or probably I misunderstood, and you mean to drop intermediate variable assignment and use V_I4(&var) directly? That would still leave the switch as a value verification step.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10609#note_139570
On Tue May 12 12:27:28 2026 +0000, Dmitry Timoshkov wrote:
Or probably I misunderstood, and you mean to drop intermediate variable assignment and use V_I4(&var) directly? That would still leave the switch as a value verification step. Yes, something like `if (V_I4(&var) & ~ADS_CHASE_REFERRALS_ALWAYS)` should be enough to catch invalid values.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10609#note_139573
participants (3)
-
Alexandre Julliard (@julliard) -
Dmitry Timoshkov -
Dmitry Timoshkov (@dmitry)