2 * Active Directory services LDAP Provider
4 * Copyright 2018 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
35 #define SECURITY_WIN32
42 #include "adsldp_private.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(adsldp
);
48 DEFINE_GUID(CLSID_LDAP
,0x228d9a81,0xc302,0x11cf,0x9a,0xa4,0x00,0xaa,0x00,0x4a,0x56,0x91);
49 DEFINE_GUID(CLSID_LDAPNamespace
,0x228d9a82,0xc302,0x11cf,0x9a,0xa4,0x00,0xaa,0x00,0x4a,0x56,0x91);
51 static HMODULE adsldp_hinst
;
53 static HRESULT
LDAPNamespace_create(REFIID riid
, void **obj
);
57 IParseDisplayName IParseDisplayName_iface
;
61 static inline LDAP_PARSE
*impl_from_IParseDisplayName(IParseDisplayName
*iface
)
63 return CONTAINING_RECORD(iface
, LDAP_PARSE
, IParseDisplayName_iface
);
66 static HRESULT WINAPI
ldap_QueryInterface(IParseDisplayName
*iface
, REFIID riid
, void **obj
)
68 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
70 if (!riid
|| !obj
) return E_INVALIDARG
;
72 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
73 IsEqualGUID(riid
, &IID_IParseDisplayName
))
75 IParseDisplayName_AddRef(iface
);
81 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
85 static ULONG WINAPI
ldap_AddRef(IParseDisplayName
*iface
)
87 LDAP_PARSE
*ldap
= impl_from_IParseDisplayName(iface
);
88 return InterlockedIncrement(&ldap
->ref
);
91 static ULONG WINAPI
ldap_Release(IParseDisplayName
*iface
)
93 LDAP_PARSE
*ldap
= impl_from_IParseDisplayName(iface
);
94 LONG ref
= InterlockedDecrement(&ldap
->ref
);
98 TRACE("destroying %p\n", iface
);
105 static HRESULT WINAPI
ldap_ParseDisplayName(IParseDisplayName
*iface
, IBindCtx
*bc
,
106 LPOLESTR name
, ULONG
*eaten
, IMoniker
**mk
)
109 IADsOpenDSObject
*ads_open
;
112 TRACE("%p,%p,%s,%p,%p\n", iface
, bc
, debugstr_w(name
), eaten
, mk
);
114 hr
= LDAPNamespace_create(&IID_IADsOpenDSObject
, (void **)&ads_open
);
115 if (hr
!= S_OK
) return hr
;
117 hr
= IADsOpenDSObject_OpenDSObject(ads_open
, name
, NULL
, NULL
, ADS_SECURE_AUTHENTICATION
, &disp
);
119 hr
= IADsOpenDSObject_OpenDSObject(ads_open
, name
, NULL
, NULL
, 0, &disp
);
122 hr
= CreatePointerMoniker((IUnknown
*)disp
, mk
);
124 *eaten
= wcslen(name
);
126 IDispatch_Release(disp
);
129 IADsOpenDSObject_Release(ads_open
);
134 static const IParseDisplayNameVtbl LDAP_PARSE_vtbl
=
139 ldap_ParseDisplayName
142 static HRESULT
LDAP_create(REFIID riid
, void **obj
)
147 ldap
= heap_alloc(sizeof(*ldap
));
148 if (!ldap
) return E_OUTOFMEMORY
;
150 ldap
->IParseDisplayName_iface
.lpVtbl
= &LDAP_PARSE_vtbl
;
153 hr
= IParseDisplayName_QueryInterface(&ldap
->IParseDisplayName_iface
, riid
, obj
);
154 IParseDisplayName_Release(&ldap
->IParseDisplayName_iface
);
161 IADsADSystemInfo IADsADSystemInfo_iface
;
165 static inline AD_sysinfo
*impl_from_IADsADSystemInfo(IADsADSystemInfo
*iface
)
167 return CONTAINING_RECORD(iface
, AD_sysinfo
, IADsADSystemInfo_iface
);
170 static HRESULT WINAPI
sysinfo_QueryInterface(IADsADSystemInfo
*iface
, REFIID riid
, void **obj
)
172 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
174 if (!riid
|| !obj
) return E_INVALIDARG
;
176 if (IsEqualGUID(riid
, &IID_IADsADSystemInfo
) ||
177 IsEqualGUID(riid
, &IID_IDispatch
) ||
178 IsEqualGUID(riid
, &IID_IUnknown
))
180 IADsADSystemInfo_AddRef(iface
);
186 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
187 return E_NOINTERFACE
;
190 static ULONG WINAPI
sysinfo_AddRef(IADsADSystemInfo
*iface
)
192 AD_sysinfo
*sysinfo
= impl_from_IADsADSystemInfo(iface
);
193 return InterlockedIncrement(&sysinfo
->ref
);
196 static ULONG WINAPI
sysinfo_Release(IADsADSystemInfo
*iface
)
198 AD_sysinfo
*sysinfo
= impl_from_IADsADSystemInfo(iface
);
199 LONG ref
= InterlockedDecrement(&sysinfo
->ref
);
203 TRACE("destroying %p\n", iface
);
210 static HRESULT WINAPI
sysinfo_GetTypeInfoCount(IADsADSystemInfo
*iface
, UINT
*count
)
212 FIXME("%p,%p: stub\n", iface
, count
);
216 static HRESULT WINAPI
sysinfo_GetTypeInfo(IADsADSystemInfo
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
218 FIXME("%p,%u,%#x,%p: stub\n", iface
, index
, lcid
, info
);
222 static HRESULT WINAPI
sysinfo_GetIDsOfNames(IADsADSystemInfo
*iface
, REFIID riid
, LPOLESTR
*names
,
223 UINT count
, LCID lcid
, DISPID
*dispid
)
225 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
229 static HRESULT WINAPI
sysinfo_Invoke(IADsADSystemInfo
*iface
, DISPID dispid
, REFIID riid
, LCID lcid
, WORD flags
,
230 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
)
232 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface
, dispid
, debugstr_guid(riid
), lcid
, flags
,
233 params
, result
, excepinfo
, argerr
);
237 static HRESULT WINAPI
sysinfo_get_UserName(IADsADSystemInfo
*iface
, BSTR
*retval
)
239 FIXME("%p,%p: stub\n", iface
, retval
);
243 static HRESULT WINAPI
sysinfo_get_ComputerName(IADsADSystemInfo
*iface
, BSTR
*retval
)
248 TRACE("%p,%p\n", iface
, retval
);
251 GetComputerObjectNameW(NameFullyQualifiedDN
, NULL
, &size
);
252 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
253 return HRESULT_FROM_WIN32(GetLastError());
255 name
= SysAllocStringLen(NULL
, size
);
256 if (!name
) return E_OUTOFMEMORY
;
258 if (!GetComputerObjectNameW(NameFullyQualifiedDN
, name
, &size
))
261 return HRESULT_FROM_WIN32(GetLastError());
268 static HRESULT WINAPI
sysinfo_get_SiteName(IADsADSystemInfo
*iface
, BSTR
*retval
)
270 FIXME("%p,%p: stub\n", iface
, retval
);
274 static HRESULT WINAPI
sysinfo_get_DomainShortName(IADsADSystemInfo
*iface
, BSTR
*retval
)
276 FIXME("%p,%p: stub\n", iface
, retval
);
280 static HRESULT WINAPI
sysinfo_get_DomainDNSName(IADsADSystemInfo
*iface
, BSTR
*retval
)
282 FIXME("%p,%p: stub\n", iface
, retval
);
286 static HRESULT WINAPI
sysinfo_get_ForestDNSName(IADsADSystemInfo
*iface
, BSTR
*retval
)
288 FIXME("%p,%p: stub\n", iface
, retval
);
292 static HRESULT WINAPI
sysinfo_get_PDCRoleOwner(IADsADSystemInfo
*iface
, BSTR
*retval
)
294 FIXME("%p,%p: stub\n", iface
, retval
);
298 static HRESULT WINAPI
sysinfo_get_SchemaRoleOwner(IADsADSystemInfo
*iface
, BSTR
*retval
)
300 FIXME("%p,%p: stub\n", iface
, retval
);
304 static HRESULT WINAPI
sysinfo_get_IsNativeMode(IADsADSystemInfo
*iface
, VARIANT_BOOL
*retval
)
306 FIXME("%p,%p: stub\n", iface
, retval
);
310 static HRESULT WINAPI
sysinfo_GetAnyDCName(IADsADSystemInfo
*iface
, BSTR
*retval
)
312 FIXME("%p,%p: stub\n", iface
, retval
);
316 static HRESULT WINAPI
sysinfo_GetDCSiteName(IADsADSystemInfo
*iface
, BSTR server
, BSTR
*retval
)
318 FIXME("%p,%s,%p: stub\n", iface
, debugstr_w(server
), retval
);
322 static HRESULT WINAPI
sysinfo_RefreshSchemaCache(IADsADSystemInfo
*iface
)
324 FIXME("%p: stub\n", iface
);
328 static HRESULT WINAPI
sysinfo_GetTrees(IADsADSystemInfo
*iface
, VARIANT
*retval
)
330 FIXME("%p,%p: stub\n", iface
, retval
);
334 static const IADsADSystemInfoVtbl IADsADSystemInfo_vtbl
=
336 sysinfo_QueryInterface
,
339 sysinfo_GetTypeInfoCount
,
341 sysinfo_GetIDsOfNames
,
343 sysinfo_get_UserName
,
344 sysinfo_get_ComputerName
,
345 sysinfo_get_SiteName
,
346 sysinfo_get_DomainShortName
,
347 sysinfo_get_DomainDNSName
,
348 sysinfo_get_ForestDNSName
,
349 sysinfo_get_PDCRoleOwner
,
350 sysinfo_get_SchemaRoleOwner
,
351 sysinfo_get_IsNativeMode
,
352 sysinfo_GetAnyDCName
,
353 sysinfo_GetDCSiteName
,
354 sysinfo_RefreshSchemaCache
,
358 static HRESULT
ADSystemInfo_create(REFIID riid
, void **obj
)
363 sysinfo
= heap_alloc(sizeof(*sysinfo
));
364 if (!sysinfo
) return E_OUTOFMEMORY
;
366 sysinfo
->IADsADSystemInfo_iface
.lpVtbl
= &IADsADSystemInfo_vtbl
;
369 hr
= IADsADSystemInfo_QueryInterface(&sysinfo
->IADsADSystemInfo_iface
, riid
, obj
);
370 IADsADSystemInfo_Release(&sysinfo
->IADsADSystemInfo_iface
);
375 struct ldap_attribute
384 IADsOpenDSObject IADsOpenDSObject_iface
;
385 IDirectorySearch IDirectorySearch_iface
;
391 ULONG attrs_count
, attrs_count_allocated
;
392 struct ldap_attribute
*attrs
;
399 struct ldap_search_context
401 LDAPMessage
*res
, *entry
;
405 static inline LDAP_namespace
*impl_from_IADs(IADs
*iface
)
407 return CONTAINING_RECORD(iface
, LDAP_namespace
, IADs_iface
);
410 static HRESULT WINAPI
ldapns_QueryInterface(IADs
*iface
, REFIID riid
, void **obj
)
412 LDAP_namespace
*ldap
= impl_from_IADs(iface
);
414 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
416 if (!riid
|| !obj
) return E_INVALIDARG
;
418 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
419 IsEqualGUID(riid
, &IID_IDispatch
) ||
420 IsEqualGUID(riid
, &IID_IADs
))
427 if (IsEqualGUID(riid
, &IID_IADsOpenDSObject
))
430 *obj
= &ldap
->IADsOpenDSObject_iface
;
434 if (IsEqualGUID(riid
, &IID_IDirectorySearch
))
437 *obj
= &ldap
->IDirectorySearch_iface
;
441 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
442 return E_NOINTERFACE
;
445 static ULONG WINAPI
ldapns_AddRef(IADs
*iface
)
447 LDAP_namespace
*ldap
= impl_from_IADs(iface
);
448 return InterlockedIncrement(&ldap
->ref
);
451 static void free_attributes(LDAP_namespace
*ldap
)
455 if (!ldap
->attrs
) return;
457 for (i
= 0; i
< ldap
->attrs_count
; i
++)
459 ldap_memfreeW(ldap
->attrs
[i
].name
);
460 ldap_value_freeW(ldap
->attrs
[i
].values
);
463 heap_free(ldap
->attrs
);
465 ldap
->attrs_count
= 0;
468 static ULONG WINAPI
ldapns_Release(IADs
*iface
)
470 LDAP_namespace
*ldap
= impl_from_IADs(iface
);
471 LONG ref
= InterlockedDecrement(&ldap
->ref
);
475 TRACE("destroying %p\n", iface
);
476 if (ldap
->ld
) ldap_unbind(ldap
->ld
);
477 SysFreeString(ldap
->host
);
478 SysFreeString(ldap
->object
);
479 free_attributes(ldap
);
486 static HRESULT WINAPI
ldapns_GetTypeInfoCount(IADs
*iface
, UINT
*count
)
488 FIXME("%p,%p: stub\n", iface
, count
);
492 static HRESULT WINAPI
ldapns_GetTypeInfo(IADs
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
494 FIXME("%p,%u,%#x,%p: stub\n", iface
, index
, lcid
, info
);
498 static HRESULT WINAPI
ldapns_GetIDsOfNames(IADs
*iface
, REFIID riid
, LPOLESTR
*names
,
499 UINT count
, LCID lcid
, DISPID
*dispid
)
501 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
505 static HRESULT WINAPI
ldapns_Invoke(IADs
*iface
, DISPID dispid
, REFIID riid
, LCID lcid
, WORD flags
,
506 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
)
508 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface
, dispid
, debugstr_guid(riid
), lcid
, flags
,
509 params
, result
, excepinfo
, argerr
);
513 static HRESULT WINAPI
ldapns_get_Name(IADs
*iface
, BSTR
*retval
)
515 FIXME("%p,%p: stub\n", iface
, retval
);
519 static HRESULT WINAPI
ldapns_get_Class(IADs
*iface
, BSTR
*retval
)
521 FIXME("%p,%p: stub\n", iface
, retval
);
525 static HRESULT WINAPI
ldapns_get_GUID(IADs
*iface
, BSTR
*retval
)
527 FIXME("%p,%p: stub\n", iface
, retval
);
531 static HRESULT WINAPI
ldapns_get_ADsPath(IADs
*iface
, BSTR
*retval
)
533 FIXME("%p,%p: stub\n", iface
, retval
);
537 static HRESULT WINAPI
ldapns_get_Parent(IADs
*iface
, BSTR
*retval
)
539 FIXME("%p,%p: stub\n", iface
, retval
);
543 static HRESULT WINAPI
ldapns_get_Schema(IADs
*iface
, BSTR
*retval
)
545 FIXME("%p,%p: stub\n", iface
, retval
);
549 static HRESULT WINAPI
ldapns_GetInfo(IADs
*iface
)
554 TRACE("%p\n", iface
);
556 hr
= ADsBuildVarArrayStr(NULL
, 0, &var
);
559 hr
= IADs_GetInfoEx(iface
, var
, 0);
565 static HRESULT WINAPI
ldapns_SetInfo(IADs
*iface
)
567 FIXME("%p: stub\n", iface
);
571 static HRESULT WINAPI
ldapns_Get(IADs
*iface
, BSTR name
, VARIANT
*prop
)
573 LDAP_namespace
*ldap
= impl_from_IADs(iface
);
577 TRACE("%p,%s,%p\n", iface
, debugstr_w(name
), prop
);
579 if (!name
|| !prop
) return E_ADS_BAD_PARAMETER
;
581 if (!ldap
->attrs_count
)
583 hr
= IADs_GetInfo(iface
);
584 if (hr
!= S_OK
) return hr
;
587 for (i
= 0; i
< ldap
->attrs_count
; i
++)
589 if (!wcsicmp(name
, ldap
->attrs
[i
].name
))
591 LONG count
= ldap_count_valuesW(ldap
->attrs
[i
].values
);
595 V_VT(prop
) = VT_BSTR
;
605 TRACE("attr %s has %u values\n", debugstr_w(ldap
->attrs
[i
].name
), count
);
607 sa
= SafeArrayCreateVector(VT_VARIANT
, 0, count
);
608 if (!sa
) return E_OUTOFMEMORY
;
610 for (idx
= 0; idx
< count
; idx
++)
612 V_VT(&item
) = VT_BSTR
;
613 V_BSTR(&item
) = SysAllocString(ldap
->attrs
[i
].values
[idx
]);
620 hr
= SafeArrayPutElement(sa
, &idx
, &item
);
621 SysFreeString(V_BSTR(&item
));
622 if (hr
!= S_OK
) goto fail
;
625 V_VT(prop
) = VT_ARRAY
| VT_VARIANT
;
629 SafeArrayDestroy(sa
);
634 V_BSTR(prop
) = SysAllocString(ldap
->attrs
[i
].values
[0]);
635 if (!V_BSTR(prop
)) return E_OUTOFMEMORY
;
636 V_VT(prop
) = VT_BSTR
;
642 return E_ADS_PROPERTY_NOT_FOUND
;
645 static HRESULT WINAPI
ldapns_Put(IADs
*iface
, BSTR name
, VARIANT prop
)
647 FIXME("%p,%s,%s: stub\n", iface
, debugstr_w(name
), wine_dbgstr_variant(&prop
));
651 static HRESULT WINAPI
ldapns_GetEx(IADs
*iface
, BSTR name
, VARIANT
*prop
)
653 FIXME("%p,%s,%p: stub\n", iface
, debugstr_w(name
), prop
);
657 static HRESULT WINAPI
ldapns_PutEx(IADs
*iface
, LONG code
, BSTR name
, VARIANT prop
)
659 FIXME("%p,%d,%s,%s: stub\n", iface
, code
, debugstr_w(name
), wine_dbgstr_variant(&prop
));
663 static HRESULT
add_attribute(LDAP_namespace
*ldap
, WCHAR
*name
, WCHAR
**values
)
665 struct ldap_attribute
*new_attrs
;
669 ldap
->attrs
= heap_alloc(256 * sizeof(ldap
->attrs
[0]));
670 if (!ldap
->attrs
) return E_OUTOFMEMORY
;
671 ldap
->attrs_count_allocated
= 256;
673 else if (ldap
->attrs_count_allocated
< ldap
->attrs_count
+ 1)
675 new_attrs
= heap_realloc(ldap
->attrs
, (ldap
->attrs_count_allocated
* 2) * sizeof(*new_attrs
));
676 if (!new_attrs
) return E_OUTOFMEMORY
;
678 ldap
->attrs_count_allocated
*= 2;
679 ldap
->attrs
= new_attrs
;
682 ldap
->attrs
[ldap
->attrs_count
].name
= name
;
683 ldap
->attrs
[ldap
->attrs_count
].values
= values
;
689 static HRESULT WINAPI
ldapns_GetInfoEx(IADs
*iface
, VARIANT prop
, LONG reserved
)
691 LDAP_namespace
*ldap
= impl_from_IADs(iface
);
695 WCHAR
**props
= NULL
, *attr
, **values
;
697 LDAPMessage
*res
= NULL
, *entry
;
700 TRACE("%p,%s,%d\n", iface
, wine_dbgstr_variant(&prop
), reserved
);
702 free_attributes(ldap
);
704 if (!ldap
->ld
) return E_NOTIMPL
;
706 if (V_VT(&prop
) != (VT_ARRAY
| VT_VARIANT
))
707 return E_ADS_BAD_PARAMETER
;
711 return E_ADS_BAD_PARAMETER
;
713 hr
= SafeArrayAccessData(sa
, (void *)&item
);
714 if (hr
!= S_OK
) return hr
;
716 count
= sa
->rgsabound
[0].cElements
;
719 props
= heap_alloc((count
+ 1) * sizeof(props
[0]));
726 for (i
= 0; i
< count
; i
++)
728 if (V_VT(&item
[i
]) != VT_BSTR
)
730 hr
= E_ADS_BAD_PARAMETER
;
733 props
[i
] = V_BSTR(&item
[i
]);
735 props
[sa
->rgsabound
[0].cElements
] = NULL
;
738 err
= ldap_search_sW(ldap
->ld
, NULL
, LDAP_SCOPE_BASE
, (WCHAR
*)L
"(objectClass=*)", props
, FALSE
, &res
);
739 if (err
!= LDAP_SUCCESS
)
741 TRACE("ldap_search_sW error %#x\n", err
);
742 hr
= HRESULT_FROM_WIN32(map_ldap_error(err
));
746 entry
= ldap_first_entry(ldap
->ld
, res
);
749 attr
= ldap_first_attributeW(ldap
->ld
, entry
, &ber
);
752 TRACE("attr: %s\n", debugstr_w(attr
));
754 values
= ldap_get_valuesW(ldap
->ld
, entry
, attr
);
756 hr
= add_attribute(ldap
, attr
, values
);
759 ldap_value_freeW(values
);
764 attr
= ldap_next_attributeW(ldap
->ld
, entry
, ber
);
767 entry
= ldap_next_entry(ldap
->ld
, res
);
771 if (res
) ldap_msgfree(res
);
773 SafeArrayUnaccessData(sa
);
777 static const IADsVtbl IADs_vtbl
=
779 ldapns_QueryInterface
,
782 ldapns_GetTypeInfoCount
,
784 ldapns_GetIDsOfNames
,
801 static inline LDAP_namespace
*impl_from_IADsOpenDSObject(IADsOpenDSObject
*iface
)
803 return CONTAINING_RECORD(iface
, LDAP_namespace
, IADsOpenDSObject_iface
);
806 static HRESULT WINAPI
openobj_QueryInterface(IADsOpenDSObject
*iface
, REFIID riid
, void **obj
)
808 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
810 if (!riid
|| !obj
) return E_INVALIDARG
;
812 if (IsEqualGUID(riid
, &IID_IADsOpenDSObject
) ||
813 IsEqualGUID(riid
, &IID_IDispatch
) ||
814 IsEqualGUID(riid
, &IID_IUnknown
))
816 IADsOpenDSObject_AddRef(iface
);
821 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
822 return E_NOINTERFACE
;
825 static ULONG WINAPI
openobj_AddRef(IADsOpenDSObject
*iface
)
827 LDAP_namespace
*ldap
= impl_from_IADsOpenDSObject(iface
);
828 return IADs_AddRef(&ldap
->IADs_iface
);
831 static ULONG WINAPI
openobj_Release(IADsOpenDSObject
*iface
)
833 LDAP_namespace
*ldap
= impl_from_IADsOpenDSObject(iface
);
834 return IADs_Release(&ldap
->IADs_iface
);
837 static HRESULT WINAPI
openobj_GetTypeInfoCount(IADsOpenDSObject
*iface
, UINT
*count
)
839 FIXME("%p,%p: stub\n", iface
, count
);
843 static HRESULT WINAPI
openobj_GetTypeInfo(IADsOpenDSObject
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
845 FIXME("%p,%u,%#x,%p: stub\n", iface
, index
, lcid
, info
);
849 static HRESULT WINAPI
openobj_GetIDsOfNames(IADsOpenDSObject
*iface
, REFIID riid
, LPOLESTR
*names
,
850 UINT count
, LCID lcid
, DISPID
*dispid
)
852 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
856 static HRESULT WINAPI
openobj_Invoke(IADsOpenDSObject
*iface
, DISPID dispid
, REFIID riid
, LCID lcid
, WORD flags
,
857 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
)
859 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface
, dispid
, debugstr_guid(riid
), lcid
, flags
,
860 params
, result
, excepinfo
, argerr
);
864 static HRESULT
parse_path(WCHAR
*path
, BSTR
*host
, ULONG
*port
, BSTR
*object
)
869 if (host
) *host
= NULL
;
871 if (object
) *object
= NULL
;
873 if (wcsnicmp(path
, L
"LDAP:", 5) != 0)
874 return E_ADS_BAD_PATHNAME
;
877 if (!*p
) return S_OK
;
879 if (*p
++ != '/' || *p
++ != '/' || !*p
)
880 return E_ADS_BAD_PATHNAME
;
884 while (*p
&& *p
!= '/')
889 if (!port
) port
= &dummy
;
890 *port
= wcstol(p
+ 1, &p
, 10);
891 if (*p
&& *p
!= '/') return E_ADS_BAD_PATHNAME
;
899 if (host_len
== 0) return E_ADS_BAD_PATHNAME
;
903 *host
= SysAllocStringLen(p_host
, host_len
);
904 if (!*host
) return E_OUTOFMEMORY
;
907 if (!*p
) return S_OK
;
909 if (*p
++ != '/' || !*p
)
911 SysFreeString(*host
);
912 return E_ADS_BAD_PATHNAME
;
917 *object
= SysAllocString(p
);
920 SysFreeString(*host
);
921 return E_OUTOFMEMORY
;
928 static HRESULT WINAPI
openobj_OpenDSObject(IADsOpenDSObject
*iface
, BSTR path
, BSTR user
, BSTR password
,
929 LONG flags
, IDispatch
**obj
)
938 TRACE("%p,%s,%s,%p,%08x,%p\n", iface
, debugstr_w(path
), debugstr_w(user
), password
, flags
, obj
);
940 hr
= parse_path(path
, &host
, &port
, &object
);
941 if (hr
!= S_OK
) return hr
;
943 TRACE("host %s, port %u, object %s\n", debugstr_w(host
), port
, debugstr_w(object
));
949 if (!wcsicmp(host
, L
"rootDSE"))
951 DOMAIN_CONTROLLER_INFOW
*dcinfo
;
955 hr
= E_ADS_BAD_PATHNAME
;
961 err
= DsGetDcNameW(NULL
, NULL
, NULL
, NULL
, DS_RETURN_DNS_NAME
, &dcinfo
);
962 if (err
!= ERROR_SUCCESS
)
964 hr
= HRESULT_FROM_WIN32(LdapGetLastError());
968 host
= SysAllocString(dcinfo
->DomainName
);
969 NetApiBufferFree(dcinfo
);
978 ld
= ldap_initW(host
, port
);
981 hr
= HRESULT_FROM_WIN32(LdapGetLastError());
985 version
= LDAP_VERSION3
;
986 err
= ldap_set_optionW(ld
, LDAP_OPT_PROTOCOL_VERSION
, &version
);
987 if (err
!= LDAP_SUCCESS
)
989 hr
= HRESULT_FROM_WIN32(map_ldap_error(err
));
994 err
= ldap_connect(ld
, NULL
);
995 if (err
!= LDAP_SUCCESS
)
997 hr
= HRESULT_FROM_WIN32(map_ldap_error(err
));
1002 if (flags
& ADS_SECURE_AUTHENTICATION
)
1004 SEC_WINNT_AUTH_IDENTITY_W id
;
1006 id
.Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1007 id
.Domain
= (unsigned short *)host
;
1008 id
.DomainLength
= wcslen(host
);
1009 id
.User
= (unsigned short *)user
;
1010 id
.UserLength
= user
? wcslen(user
) : 0;
1011 id
.Password
= (unsigned short *)password
;
1012 id
.PasswordLength
= password
? wcslen(password
) : 0;
1014 err
= ldap_bind_sW(ld
, NULL
, (WCHAR
*)&id
, LDAP_AUTH_NEGOTIATE
);
1015 if (err
!= LDAP_SUCCESS
)
1017 TRACE("ldap_bind_sW error %#x\n", err
);
1018 hr
= HRESULT_FROM_WIN32(map_ldap_error(err
));
1025 err
= ldap_simple_bind_sW(ld
, user
, password
);
1026 if (err
!= LDAP_SUCCESS
)
1028 TRACE("ldap_simple_bind_sW error %#x\n", err
);
1029 hr
= HRESULT_FROM_WIN32(map_ldap_error(err
));
1036 hr
= LDAPNamespace_create(&IID_IADs
, (void **)&ads
);
1039 LDAP_namespace
*ldap
= impl_from_IADs(ads
);
1043 ldap
->object
= object
;
1044 hr
= IADs_QueryInterface(ads
, &IID_IDispatch
, (void **)obj
);
1050 SysFreeString(host
);
1051 SysFreeString(object
);
1056 static const IADsOpenDSObjectVtbl IADsOpenDSObject_vtbl
=
1058 openobj_QueryInterface
,
1061 openobj_GetTypeInfoCount
,
1062 openobj_GetTypeInfo
,
1063 openobj_GetIDsOfNames
,
1065 openobj_OpenDSObject
1068 static inline LDAP_namespace
*impl_from_IDirectorySearch(IDirectorySearch
*iface
)
1070 return CONTAINING_RECORD(iface
, LDAP_namespace
, IDirectorySearch_iface
);
1073 static HRESULT WINAPI
search_QueryInterface(IDirectorySearch
*iface
, REFIID riid
, void **obj
)
1075 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
1077 if (!riid
|| !obj
) return E_INVALIDARG
;
1079 if (IsEqualGUID(riid
, &IID_IDirectorySearch
) ||
1080 IsEqualGUID(riid
, &IID_IUnknown
))
1082 IDirectorySearch_AddRef(iface
);
1087 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
1088 return E_NOINTERFACE
;
1091 static ULONG WINAPI
search_AddRef(IDirectorySearch
*iface
)
1093 LDAP_namespace
*ldap
= impl_from_IDirectorySearch(iface
);
1094 return IADs_AddRef(&ldap
->IADs_iface
);
1097 static ULONG WINAPI
search_Release(IDirectorySearch
*iface
)
1099 LDAP_namespace
*ldap
= impl_from_IDirectorySearch(iface
);
1100 return IADs_Release(&ldap
->IADs_iface
);
1103 static HRESULT WINAPI
search_SetSearchPreference(IDirectorySearch
*iface
, PADS_SEARCHPREF_INFO prefs
, DWORD count
)
1105 LDAP_namespace
*ldap
= impl_from_IDirectorySearch(iface
);
1108 TRACE("%p,%p,%u\n", iface
, prefs
, count
);
1110 for (i
= 0; i
< count
; i
++)
1112 switch (prefs
[i
].dwSearchPref
)
1114 case ADS_SEARCHPREF_SEARCH_SCOPE
:
1115 if (prefs
[i
].vValue
.dwType
!= ADSTYPE_INTEGER
)
1117 FIXME("ADS_SEARCHPREF_SEACH_SCOPE: not supportd dwType %d\n", prefs
[i
].vValue
.dwType
);
1118 prefs
[i
].dwStatus
= ADS_STATUS_INVALID_SEARCHPREFVALUE
;
1122 switch (prefs
[i
].vValue
.u
.Integer
)
1124 case ADS_SCOPE_BASE
:
1125 case ADS_SCOPE_ONELEVEL
:
1126 case ADS_SCOPE_SUBTREE
:
1127 TRACE("SEARCH_SCOPE: %d\n", prefs
[i
].vValue
.u
.Integer
);
1128 ldap
->search
.scope
= prefs
[i
].vValue
.u
.Integer
;
1129 prefs
[i
].dwStatus
= ADS_STATUS_S_OK
;
1133 prefs
[i
].dwStatus
= ADS_STATUS_INVALID_SEARCHPREFVALUE
;
1139 FIXME("pref %d, type %u: stub\n", prefs
[i
].dwSearchPref
, prefs
[i
].vValue
.dwType
);
1140 prefs
[i
].dwStatus
= ADS_STATUS_INVALID_SEARCHPREF
;
1148 static HRESULT WINAPI
search_ExecuteSearch(IDirectorySearch
*iface
, LPWSTR filter
, LPWSTR
*names
,
1149 DWORD count
, PADS_SEARCH_HANDLE res
)
1151 LDAP_namespace
*ldap
= impl_from_IDirectorySearch(iface
);
1154 struct ldap_search_context
*ldap_ctx
;
1156 TRACE("%p,%s,%p,%u,%p\n", iface
, debugstr_w(filter
), names
, count
, res
);
1158 if (!ldap
->ld
) return E_NOTIMPL
;
1160 if (!res
) return E_ADS_BAD_PARAMETER
;
1162 ldap_ctx
= heap_alloc_zero(sizeof(*ldap_ctx
));
1163 if (!ldap_ctx
) return E_OUTOFMEMORY
;
1165 if (count
== 0xffffffff)
1169 if (count
&& !names
) return E_ADS_BAD_PARAMETER
;
1171 props
= heap_alloc((count
+ 1) * sizeof(props
[0]));
1174 heap_free(ldap_ctx
);
1175 return E_OUTOFMEMORY
;
1178 for (i
= 0; i
< count
; i
++)
1179 props
[i
] = names
[i
];
1181 props
[count
] = NULL
;
1184 err
= ldap_search_sW(ldap
->ld
, ldap
->object
, ldap
->search
.scope
, filter
, props
, FALSE
, &ldap_ctx
->res
);
1186 if (err
!= LDAP_SUCCESS
)
1188 TRACE("ldap_search_sW error %#x\n", err
);
1189 heap_free(ldap_ctx
);
1190 return HRESULT_FROM_WIN32(map_ldap_error(err
));
1197 static HRESULT WINAPI
search_AbandonSearch(IDirectorySearch
*iface
, ADS_SEARCH_HANDLE res
)
1199 FIXME("%p,%p: stub\n", iface
, res
);
1203 static HRESULT WINAPI
search_GetFirstRow(IDirectorySearch
*iface
, ADS_SEARCH_HANDLE res
)
1205 LDAP_namespace
*ldap
= impl_from_IDirectorySearch(iface
);
1206 struct ldap_search_context
*ldap_ctx
= res
;
1208 TRACE("%p,%p\n", iface
, res
);
1210 if (!ldap
->ld
) return E_NOTIMPL
;
1212 if (!res
) return E_ADS_BAD_PARAMETER
;
1214 ldap_ctx
->count
= ldap_count_entries(ldap
->ld
, ldap_ctx
->res
);
1216 ldap_ctx
->entry
= ldap_first_entry(ldap
->ld
, ldap_ctx
->res
);
1218 return ldap_ctx
->entry
? S_OK
: S_ADS_NOMORE_ROWS
;
1221 static HRESULT WINAPI
search_GetNextRow(IDirectorySearch
*iface
, ADS_SEARCH_HANDLE res
)
1223 LDAP_namespace
*ldap
= impl_from_IDirectorySearch(iface
);
1224 struct ldap_search_context
*ldap_ctx
= res
;
1226 TRACE("%p,%p\n", iface
, res
);
1228 if (!ldap
->ld
) return E_NOTIMPL
;
1230 if (!res
) return E_ADS_BAD_PARAMETER
;
1232 if (!ldap_ctx
->entry
)
1234 ldap_ctx
->count
= ldap_count_entries(ldap
->ld
, ldap_ctx
->res
);
1236 ldap_ctx
->entry
= ldap_first_entry(ldap
->ld
, ldap_ctx
->res
);
1240 if (ldap_ctx
->pos
>= ldap_ctx
->count
)
1241 return S_ADS_NOMORE_ROWS
;
1243 ldap_ctx
->entry
= ldap_next_entry(ldap
->ld
, ldap_ctx
->res
);
1247 return ldap_ctx
->entry
? S_OK
: S_ADS_NOMORE_ROWS
;
1250 static HRESULT WINAPI
search_GetPreviousRow(IDirectorySearch
*iface
, ADS_SEARCH_HANDLE res
)
1252 FIXME("%p,%p: stub\n", iface
, res
);
1256 static HRESULT WINAPI
search_GetNextColumnName(IDirectorySearch
*iface
, ADS_SEARCH_HANDLE res
, LPWSTR
*names
)
1258 FIXME("%p,%p,%p: stub\n", iface
, res
, names
);
1262 static HRESULT WINAPI
search_GetColumn(IDirectorySearch
*iface
, ADS_SEARCH_HANDLE res
,
1263 LPWSTR name
, PADS_SEARCH_COLUMN col
)
1265 FIXME("%p,%p,%s,%p: stub\n", iface
, res
, debugstr_w(name
), col
);
1269 static HRESULT WINAPI
search_FreeColumn(IDirectorySearch
*iface
, PADS_SEARCH_COLUMN col
)
1271 FIXME("%p,%p: stub\n", iface
, col
);
1275 static HRESULT WINAPI
search_CloseSearchHandle(IDirectorySearch
*iface
, ADS_SEARCH_HANDLE res
)
1277 struct ldap_search_context
*ldap_ctx
= res
;
1279 TRACE("%p,%p\n", iface
, res
);
1281 if (!res
) return E_ADS_BAD_PARAMETER
;
1283 ldap_msgfree(ldap_ctx
->res
);
1288 static const IDirectorySearchVtbl IDirectorySearch_vtbl
=
1290 search_QueryInterface
,
1293 search_SetSearchPreference
,
1294 search_ExecuteSearch
,
1295 search_AbandonSearch
,
1298 search_GetPreviousRow
,
1299 search_GetNextColumnName
,
1302 search_CloseSearchHandle
1305 static HRESULT
LDAPNamespace_create(REFIID riid
, void **obj
)
1307 LDAP_namespace
*ldap
;
1310 ldap
= heap_alloc(sizeof(*ldap
));
1311 if (!ldap
) return E_OUTOFMEMORY
;
1313 ldap
->IADs_iface
.lpVtbl
= &IADs_vtbl
;
1314 ldap
->IADsOpenDSObject_iface
.lpVtbl
= &IADsOpenDSObject_vtbl
;
1315 ldap
->IDirectorySearch_iface
.lpVtbl
= &IDirectorySearch_vtbl
;
1319 ldap
->object
= NULL
;
1320 ldap
->attrs_count
= 0;
1321 ldap
->attrs_count_allocated
= 0;
1323 ldap
->search
.scope
= ADS_SCOPE_SUBTREE
;
1325 hr
= IADs_QueryInterface(&ldap
->IADs_iface
, riid
, obj
);
1326 IADs_Release(&ldap
->IADs_iface
);
1331 static const struct class_info
1334 HRESULT (*constructor
)(REFIID
, void **);
1337 { &CLSID_ADSystemInfo
, ADSystemInfo_create
},
1338 { &CLSID_LDAP
, LDAP_create
},
1339 { &CLSID_LDAPNamespace
, LDAPNamespace_create
},
1344 IClassFactory IClassFactory_iface
;
1346 const struct class_info
*info
;
1349 static inline class_factory
*impl_from_IClassFactory(IClassFactory
*iface
)
1351 return CONTAINING_RECORD(iface
, class_factory
, IClassFactory_iface
);
1354 static HRESULT WINAPI
factory_QueryInterface(IClassFactory
*iface
, REFIID riid
, LPVOID
*obj
)
1356 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
1358 if (!riid
|| !obj
) return E_INVALIDARG
;
1360 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1361 IsEqualIID(riid
, &IID_IClassFactory
))
1363 IClassFactory_AddRef(iface
);
1369 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
1370 return E_NOINTERFACE
;
1373 static ULONG WINAPI
factory_AddRef(IClassFactory
*iface
)
1375 class_factory
*factory
= impl_from_IClassFactory(iface
);
1376 ULONG ref
= InterlockedIncrement(&factory
->ref
);
1378 TRACE("(%p) ref %u\n", iface
, ref
);
1383 static ULONG WINAPI
factory_Release(IClassFactory
*iface
)
1385 class_factory
*factory
= impl_from_IClassFactory(iface
);
1386 ULONG ref
= InterlockedDecrement(&factory
->ref
);
1388 TRACE("(%p) ref %u\n", iface
, ref
);
1396 static HRESULT WINAPI
factory_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **obj
)
1398 class_factory
*factory
= impl_from_IClassFactory(iface
);
1400 TRACE("%p,%s,%p\n", outer
, debugstr_guid(riid
), obj
);
1402 if (!riid
|| !obj
) return E_INVALIDARG
;
1405 if (outer
) return CLASS_E_NOAGGREGATION
;
1407 return factory
->info
->constructor(riid
, obj
);
1410 static HRESULT WINAPI
factory_LockServer(IClassFactory
*iface
, BOOL lock
)
1412 FIXME("%p,%d: stub\n", iface
, lock
);
1416 static const struct IClassFactoryVtbl factory_vtbl
=
1418 factory_QueryInterface
,
1421 factory_CreateInstance
,
1425 static HRESULT
factory_constructor(const struct class_info
*info
, REFIID riid
, void **obj
)
1427 class_factory
*factory
;
1430 factory
= heap_alloc(sizeof(*factory
));
1431 if (!factory
) return E_OUTOFMEMORY
;
1433 factory
->IClassFactory_iface
.lpVtbl
= &factory_vtbl
;
1435 factory
->info
= info
;
1437 hr
= IClassFactory_QueryInterface(&factory
->IClassFactory_iface
, riid
, obj
);
1438 IClassFactory_Release(&factory
->IClassFactory_iface
);
1443 HRESULT WINAPI
DllGetClassObject(REFCLSID clsid
, REFIID iid
, LPVOID
*obj
)
1447 TRACE("%s,%s,%p\n", debugstr_guid(clsid
), debugstr_guid(iid
), obj
);
1449 if (!clsid
|| !iid
|| !obj
) return E_INVALIDARG
;
1453 for (i
= 0; i
< ARRAY_SIZE(class_info
); i
++)
1455 if (IsEqualCLSID(class_info
[i
].clsid
, clsid
))
1456 return factory_constructor(&class_info
[i
], iid
, obj
);
1459 FIXME("class %s/%s is not implemented\n", debugstr_guid(clsid
), debugstr_guid(iid
));
1460 return CLASS_E_CLASSNOTAVAILABLE
;
1463 HRESULT WINAPI
DllCanUnloadNow(void)
1468 HRESULT WINAPI
DllRegisterServer(void)
1470 return __wine_register_resources(adsldp_hinst
);
1473 HRESULT WINAPI
DllUnregisterServer(void)
1475 return __wine_unregister_resources(adsldp_hinst
);
1478 BOOL WINAPI
DllMain(HINSTANCE hinst
, DWORD reason
, void *reserved
)
1480 TRACE("%p,%u,%p\n", hinst
, reason
, reserved
);
1484 case DLL_WINE_PREATTACH
:
1485 return FALSE
; /* prefer native version */
1487 case DLL_PROCESS_ATTACH
:
1488 adsldp_hinst
= hinst
;
1489 DisableThreadLibraryCalls(hinst
);