diff --git a/dlls/adsldp/Makefile.in b/dlls/adsldp/Makefile.in index 6d760c86823..cfa84c3fd04 100644 --- a/dlls/adsldp/Makefile.in +++ b/dlls/adsldp/Makefile.in @@ -1,5 +1,5 @@ MODULE = adsldp.dll -IMPORTS = oleaut32 secur32 +IMPORTS = ole32 oleaut32 secur32 EXTRADLLFLAGS = -mno-cygwin diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c index 7281375e91e..5432a0abe22 100644 --- a/dlls/adsldp/adsldp.c +++ b/dlls/adsldp/adsldp.c @@ -36,10 +36,95 @@ WINE_DEFAULT_DEBUG_CHANNEL(adsldp); +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); static HMODULE adsldp_hinst; +static HRESULT LDAPNamespace_create(REFIID riid, void **obj); + +typedef struct +{ + IParseDisplayName IParseDisplayName_iface; + LONG ref; +} LDAP_PARSE; + +static inline LDAP_PARSE *impl_from_IParseDisplayName(IParseDisplayName *iface) +{ + return CONTAINING_RECORD(iface, LDAP_PARSE, IParseDisplayName_iface); +} + +static HRESULT WINAPI ldap_QueryInterface(IParseDisplayName *iface, REFIID riid, void **obj) +{ + TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); + + if (!riid || !obj) return E_INVALIDARG; + + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IParseDisplayName)) + { + IParseDisplayName_AddRef(iface); + *obj = iface; + return S_OK; + } + + *obj = NULL; + FIXME("interface %s is not implemented\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI ldap_AddRef(IParseDisplayName *iface) +{ + LDAP_PARSE *ldap = impl_from_IParseDisplayName(iface); + return InterlockedIncrement(&ldap->ref); +} + +static ULONG WINAPI ldap_Release(IParseDisplayName *iface) +{ + LDAP_PARSE *ldap = impl_from_IParseDisplayName(iface); + LONG ref = InterlockedDecrement(&ldap->ref); + + if (!ref) + { + TRACE("destroying %p\n", iface); + heap_free(ldap); + } + + return ref; +} + +static HRESULT WINAPI ldap_ParseDisplayName(IParseDisplayName *iface, IBindCtx *bc, + LPOLESTR name, ULONG *eaten, IMoniker **mk) +{ + FIXME("%p,%p,%s,%p,%p: stub\n", iface, bc, debugstr_w(name), eaten, mk); + return E_NOTIMPL; +} + +static const IParseDisplayNameVtbl LDAP_PARSE_vtbl = +{ + ldap_QueryInterface, + ldap_AddRef, + ldap_Release, + ldap_ParseDisplayName +}; + +static HRESULT LDAP_create(REFIID riid, void **obj) +{ + LDAP_PARSE *ldap; + HRESULT hr; + + ldap = heap_alloc(sizeof(*ldap)); + if (!ldap) return E_OUTOFMEMORY; + + ldap->IParseDisplayName_iface.lpVtbl = &LDAP_PARSE_vtbl; + ldap->ref = 1; + + hr = IParseDisplayName_QueryInterface(&ldap->IParseDisplayName_iface, riid, obj); + IParseDisplayName_Release(&ldap->IParseDisplayName_iface); + + return hr; +} + typedef struct { IADsADSystemInfo IADsADSystemInfo_iface; @@ -66,6 +151,7 @@ static HRESULT WINAPI sysinfo_QueryInterface(IADsADSystemInfo *iface, REFIID rii return S_OK; } + *obj = NULL; FIXME("interface %s is not implemented\n", debugstr_guid(riid)); return E_NOINTERFACE; } @@ -560,6 +646,7 @@ static const struct class_info } class_info[] = { { &CLSID_ADSystemInfo, ADSystemInfo_create }, + { &CLSID_LDAP, LDAP_create }, { &CLSID_LDAPNamespace, LDAPNamespace_create }, }; @@ -666,7 +753,6 @@ static HRESULT factory_constructor(const struct class_info *info, REFIID riid, v HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID *obj) { - const struct class_info *info = NULL; int i; TRACE("%s,%s,%p\n", debugstr_guid(clsid), debugstr_guid(iid), obj); @@ -678,15 +764,9 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID *obj) for (i = 0; i < ARRAY_SIZE(class_info); i++) { if (IsEqualCLSID(class_info[i].clsid, clsid)) - { - info = &class_info[i]; - break; - } + return factory_constructor(&class_info[i], iid, obj); } - if (info) - return factory_constructor(info, iid, obj); - FIXME("class %s/%s is not implemented\n", debugstr_guid(clsid), debugstr_guid(iid)); return CLASS_E_CLASSNOTAVAILABLE; } diff --git a/dlls/adsldp/adsldp.idl b/dlls/adsldp/adsldp.idl index b9549419e24..85190bc6936 100644 --- a/dlls/adsldp/adsldp.idl +++ b/dlls/adsldp/adsldp.idl @@ -20,6 +20,14 @@ #pragma makedep register +[ + helpstring("LDAP Provider Object"), + progid("LDAP"), + uuid(228d9a81-c302-11cf-9aa4-00aa004a5691), + threading(both) +] +coclass LDAP { interface IParseDisplayName; } + [ helpstring("LDAP Namespace Object"), progid("LDAPNamespace"), diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c index e2ce9ee1a2e..cc0b42c1c59 100644 --- a/dlls/adsldp/tests/ldap.c +++ b/dlls/adsldp/tests/ldap.c @@ -27,11 +27,36 @@ #include "winbase.h" #include "objbase.h" #include "iads.h" +#include "adserr.h" #include "wine/test.h" #include "initguid.h" +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); +DEFINE_OLEGUID(CLSID_PointerMoniker,0x306,0,0); + +static const struct +{ + const WCHAR *path; + HRESULT hr, hr_ads_open, hr_ads_get; +} test[] = +{ + { L"invalid", MK_E_SYNTAX, E_ADS_BAD_PATHNAME, E_FAIL }, + { L"LDAP", MK_E_SYNTAX, E_ADS_BAD_PATHNAME, E_FAIL }, + { L"LDAP:", S_OK }, + { L"LDAP:/", E_ADS_BAD_PATHNAME }, + { L"LDAP://", E_ADS_BAD_PATHNAME }, + { L"LDAP://ldap.forumsys.com", S_OK }, + { L"LDAP:///ldap.forumsys.com", E_ADS_BAD_PATHNAME }, + { L"LDAP://ldap.forumsys.com:389", S_OK }, + { L"LDAP://ldap.forumsys.com:389/DC=example,DC=com", S_OK }, + { L"LDAP://ldap.forumsys.com/", E_ADS_BAD_PATHNAME }, + { L"LDAP://ldap.forumsys.com/rootDSE", S_OK }, + { L"LDAP://ldap.forumsys.com/rootDSE/", E_ADS_BAD_PATHNAME }, + { L"LDAP://ldap.forumsys.com/rootDSE/invalid", E_ADS_BAD_PATHNAME }, + /*{ L"LDAP://invalid", __HRESULT_FROM_WIN32(ERROR_DS_INVALID_DN_SYNTAX) }, takes way too much time */ +}; static void test_LDAP(void) { @@ -68,6 +93,72 @@ if (hr == S_OK) IUnknown_Release(unk); } +static void test_ParseDisplayName(void) +{ + HRESULT hr; + IBindCtx *bc; + IParseDisplayName *parse; + IMoniker *mk; + IUnknown *unk; + CLSID clsid; + BSTR path; + ULONG count; + int i; + + hr = CoCreateInstance(&CLSID_LDAP, 0, CLSCTX_INPROC_SERVER, &IID_IParseDisplayName, (void **)&parse); + ok(hr == S_OK, "got %#x\n", hr); + IParseDisplayName_Release(parse); + + hr = CoCreateInstance(&CLSID_LDAP, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); + ok(hr == S_OK, "got %#x\n", hr); + hr = IUnknown_QueryInterface(unk, &IID_IParseDisplayName, (void **)&parse); + ok(hr == S_OK, "got %#x\n", hr); + IUnknown_Release(unk); + + hr = CreateBindCtx(0, &bc); + ok(hr == S_OK, "got %#x\n", hr); + + for (i = 0; i < ARRAY_SIZE(test); i++) + { + path = SysAllocString(test[i].path); + + count = 0xdeadbeef; + hr = IParseDisplayName_ParseDisplayName(parse, bc, path, &count, &mk); +todo_wine + ok(hr == test[i].hr || hr == test[i].hr_ads_open, "%d: got %#x, expected %#x\n", i, hr, test[i].hr); + if (hr == S_OK) + { + ok(count == lstrlenW(test[i].path), "%d: got %d\n", i, count); + + hr = IMoniker_GetClassID(mk, &clsid); + ok(hr == S_OK, "got %#x\n", hr); + ok(IsEqualGUID(&clsid, &CLSID_PointerMoniker), "%d: got %s\n", i, wine_dbgstr_guid(&clsid)); + + IMoniker_Release(mk); + } + + SysFreeString(path); + + count = 0xdeadbeef; + hr = MkParseDisplayName(bc, test[i].path, &count, &mk); +todo_wine + ok(hr == test[i].hr, "%d: got %#x, expected %#x\n", i, hr, test[i].hr); + if (hr == S_OK) + { + ok(count == lstrlenW(test[i].path), "%d: got %d\n", i, count); + + hr = IMoniker_GetClassID(mk, &clsid); + ok(hr == S_OK, "got %#x\n", hr); + ok(IsEqualGUID(&clsid, &CLSID_PointerMoniker), "%d: got %s\n", i, wine_dbgstr_guid(&clsid)); + + IMoniker_Release(mk); + } + } + + IBindCtx_Release(bc); + IParseDisplayName_Release(parse); +} + START_TEST(ldap) { HRESULT hr; @@ -76,6 +167,7 @@ START_TEST(ldap) ok(hr == S_OK, "got %#x\n", hr); test_LDAP(); + test_ParseDisplayName(); CoUninitialize(); }