From b8b836e43ddb0c85236eacdb54be6e74f92ac291 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 17 Dec 2019 18:56:36 +1100 Subject: [PATCH] Added activeds-ADsOpenObject patchset --- .../0001-include-Add-adserr.h.patch | 72 +++ ...002-activeds-Implement-ADsOpenObject.patch | 161 ++++++ .../0003-adsldp-Add-LDAPNamespace-stubs.patch | 483 ++++++++++++++++++ ...04-adsldp-Add-IADsOpenDSObject-stubs.patch | 156 ++++++ ...sts-Add-some-tests-for-LDAPNamespace.patch | 123 +++++ patches/activeds-ADsOpenObject/definition | 2 + patches/patchinstall.sh | 29 ++ 7 files changed, 1026 insertions(+) create mode 100644 patches/activeds-ADsOpenObject/0001-include-Add-adserr.h.patch create mode 100644 patches/activeds-ADsOpenObject/0002-activeds-Implement-ADsOpenObject.patch create mode 100644 patches/activeds-ADsOpenObject/0003-adsldp-Add-LDAPNamespace-stubs.patch create mode 100644 patches/activeds-ADsOpenObject/0004-adsldp-Add-IADsOpenDSObject-stubs.patch create mode 100644 patches/activeds-ADsOpenObject/0005-adsldp-tests-Add-some-tests-for-LDAPNamespace.patch create mode 100644 patches/activeds-ADsOpenObject/definition diff --git a/patches/activeds-ADsOpenObject/0001-include-Add-adserr.h.patch b/patches/activeds-ADsOpenObject/0001-include-Add-adserr.h.patch new file mode 100644 index 00000000..56769c16 --- /dev/null +++ b/patches/activeds-ADsOpenObject/0001-include-Add-adserr.h.patch @@ -0,0 +1,72 @@ +From f517c6095f355529ccbd44585d22458fb52f9197 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Fri, 15 Nov 2019 15:46:23 +0800 +Subject: [PATCH 1/5] include: Add adserr.h. +Content-Type: text/plain; charset=UTF-8 +To: wine-devel@winehq.org + +Signed-off-by: Dmitry Timoshkov +--- + include/adserr.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + create mode 100644 include/adserr.h + +diff --git a/include/adserr.h b/include/adserr.h +new file mode 100644 +index 0000000000..83da568763 +--- /dev/null ++++ b/include/adserr.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (C) 2019 Dmitry Timoshkov ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#ifndef __ADSERR_H ++#define __ADSERR_H ++ ++#ifdef RC_INVOKED ++#define _HRESULT_TYPEDEF_(x) (x) ++#else ++#define _HRESULT_TYPEDEF_(x) ((HRESULT)x) ++#endif ++ ++#define E_ADS_BAD_PATHNAME _HRESULT_TYPEDEF_(0x80005000) ++#define E_ADS_INVALID_DOMAIN_OBJECT _HRESULT_TYPEDEF_(0x80005001) ++#define E_ADS_INVALID_USER_OBJECT _HRESULT_TYPEDEF_(0x80005002) ++#define E_ADS_INVALID_COMPUTER_OBJECT _HRESULT_TYPEDEF_(0x80005003) ++#define E_ADS_UNKNOWN_OBJECT _HRESULT_TYPEDEF_(0x80005004) ++#define E_ADS_PROPERTY_NOT_SET _HRESULT_TYPEDEF_(0x80005005) ++#define E_ADS_PROPERTY_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80005006) ++#define E_ADS_PROPERTY_INVALID _HRESULT_TYPEDEF_(0x80005007) ++#define E_ADS_BAD_PARAMETER _HRESULT_TYPEDEF_(0x80005008) ++#define E_ADS_OBJECT_UNBOUND _HRESULT_TYPEDEF_(0x80005009) ++#define E_ADS_PROPERTY_NOT_MODIFIED _HRESULT_TYPEDEF_(0x8000500A) ++#define E_ADS_PROPERTY_MODIFIED _HRESULT_TYPEDEF_(0x8000500B) ++#define E_ADS_CANT_CONVERT_DATATYPE _HRESULT_TYPEDEF_(0x8000500C) ++#define E_ADS_PROPERTY_NOT_FOUND _HRESULT_TYPEDEF_(0x8000500D) ++#define E_ADS_OBJECT_EXISTS _HRESULT_TYPEDEF_(0x8000500E) ++#define E_ADS_SCHEMA_VIOLATION _HRESULT_TYPEDEF_(0x8000500F) ++#define E_ADS_COLUMN_NOT_SET _HRESULT_TYPEDEF_(0x80005010) ++#define S_ADS_ERRORSOCCURRED _HRESULT_TYPEDEF_(0x00005011) ++#define S_ADS_NOMORE_ROWS _HRESULT_TYPEDEF_(0x00005012) ++#define S_ADS_NOMORE_COLUMNS _HRESULT_TYPEDEF_(0x00005013) ++#define E_ADS_INVALID_FILTER _HRESULT_TYPEDEF_(0x80005014) ++ ++#endif /* __ADSERR_H */ +-- +2.20.1 + diff --git a/patches/activeds-ADsOpenObject/0002-activeds-Implement-ADsOpenObject.patch b/patches/activeds-ADsOpenObject/0002-activeds-Implement-ADsOpenObject.patch new file mode 100644 index 00000000..42444c61 --- /dev/null +++ b/patches/activeds-ADsOpenObject/0002-activeds-Implement-ADsOpenObject.patch @@ -0,0 +1,161 @@ +From c12e335b0df736fe2a2f2447d0d751de7cc21d37 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Fri, 15 Nov 2019 17:37:11 +0800 +Subject: [PATCH 2/5] activeds: Implement ADsOpenObject. +Content-Type: text/plain; charset=UTF-8 +To: wine-devel@winehq.org + +Signed-off-by: Dmitry Timoshkov +--- + dlls/activeds/Makefile.in | 1 + + dlls/activeds/activeds_main.c | 80 +++++++++++++++++++++++++++++++++-- + include/iads.idl | 14 ++++++ + 3 files changed, 91 insertions(+), 4 deletions(-) + +diff --git a/dlls/activeds/Makefile.in b/dlls/activeds/Makefile.in +index 20578a93bc..54f86d661e 100644 +--- a/dlls/activeds/Makefile.in ++++ b/dlls/activeds/Makefile.in +@@ -1,5 +1,6 @@ + MODULE = activeds.dll + IMPORTLIB = activeds ++IMPORTS = advapi32 ole32 oleaut32 + + EXTRADLLFLAGS = -mno-cygwin + +diff --git a/dlls/activeds/activeds_main.c b/dlls/activeds/activeds_main.c +index 69c5c447dc..8ff587e332 100644 +--- a/dlls/activeds/activeds_main.c ++++ b/dlls/activeds/activeds_main.c +@@ -2,6 +2,7 @@ + * Implementation of the Active Directory Service Interface + * + * Copyright 2005 Detlef Riekenberg ++ * Copyright 2019 Dmitry Timoshkov + * + * This file contains only stubs to get the printui.dll up and running + * activeds.dll is much much more than this +@@ -30,8 +31,10 @@ + #include "winuser.h" + + #include "objbase.h" ++#include "initguid.h" + #include "iads.h" + #include "adshlp.h" ++#include "adserr.h" + + #include "wine/debug.h" + +@@ -112,11 +115,80 @@ HRESULT WINAPI ADsBuildVarArrayInt(LPDWORD lpdwObjectTypes, DWORD dwObjectTypes, + /***************************************************** + * ADsOpenObject [ACTIVEDS.9] + */ +-HRESULT WINAPI ADsOpenObject(LPCWSTR lpszPathName, LPCWSTR lpszUserName, LPCWSTR lpszPassword, DWORD dwReserved, REFIID riid, VOID** ppObject) ++HRESULT WINAPI ADsOpenObject(LPCWSTR path, LPCWSTR user, LPCWSTR password, DWORD reserved, REFIID riid, void **obj) + { +- FIXME("(%s,%s,%u,%s,%p)!stub\n", debugstr_w(lpszPathName), +- debugstr_w(lpszUserName), dwReserved, debugstr_guid(riid), ppObject); +- return E_NOTIMPL; ++ HRESULT hr; ++ HKEY hkey, hprov; ++ WCHAR provider[MAX_PATH], progid[MAX_PATH]; ++ DWORD idx = 0; ++ ++ TRACE("(%s,%s,%u,%s,%p)\n", debugstr_w(path), debugstr_w(user), reserved, debugstr_guid(riid), obj); ++ ++ if (!path || !riid || !obj) ++ return E_INVALIDARG; ++ ++ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\ADs\\Providers", 0, KEY_READ, &hkey)) ++ return E_ADS_BAD_PATHNAME; ++ ++ hr = E_ADS_BAD_PATHNAME; ++ ++ for (;;) ++ { ++ if (RegEnumKeyW(hkey, idx++, provider, ARRAY_SIZE(provider))) ++ break; ++ ++ TRACE("provider %s\n", debugstr_w(provider)); ++ ++ if (!wcsnicmp(path, provider, wcslen(provider)) && path[wcslen(provider)] == ':') ++ { ++ LONG size; ++ ++ if (RegOpenKeyExW(hkey, provider, 0, KEY_READ, &hprov)) ++ break; ++ ++ size = ARRAY_SIZE(progid); ++ if (!RegQueryValueW(hprov, NULL, progid, &size)) ++ { ++ CLSID clsid; ++ ++ if (CLSIDFromProgID(progid, &clsid) == S_OK) ++ { ++ IADsOpenDSObject *adsopen; ++ IDispatch *disp; ++ ++ TRACE("ns %s => clsid %s\n", debugstr_w(progid), wine_dbgstr_guid(&clsid)); ++ if (CoCreateInstance(&clsid, 0, CLSCTX_INPROC_SERVER, &IID_IADsOpenDSObject, (void **)&adsopen) == S_OK) ++ { ++ BSTR bpath, buser, bpassword; ++ ++ bpath = SysAllocString(path); ++ buser = SysAllocString(user); ++ bpassword = SysAllocString(password); ++ ++ hr = IADsOpenDSObject_OpenDSObject(adsopen, bpath, buser, bpassword, reserved, &disp); ++ if (hr == S_OK) ++ { ++ hr = IDispatch_QueryInterface(disp, riid, obj); ++ IDispatch_Release(disp); ++ } ++ ++ SysFreeString(bpath); ++ SysFreeString(buser); ++ SysFreeString(bpassword); ++ ++ IADsOpenDSObject_Release(adsopen); ++ } ++ } ++ } ++ ++ RegCloseKey(hprov); ++ break; ++ } ++ } ++ ++ RegCloseKey(hkey); ++ ++ return hr; + } + + /***************************************************** +diff --git a/include/iads.idl b/include/iads.idl +index 6931b6f734..add52571c7 100644 +--- a/include/iads.idl ++++ b/include/iads.idl +@@ -794,6 +794,20 @@ interface IDirectorySearch : IUnknown + HRESULT CloseSearchHandle([in] ADS_SEARCH_HANDLE hSearchResult); + } + ++/***************************************************************************** ++ * IID_IADsOpenDSObject interface ++ */ ++[ ++ odl, ++ uuid(ddf2891e-0f9c-11d0-8ad4-00c04fd8d503), ++ dual, ++ oleautomation ++] ++interface IADsOpenDSObject : IDispatch ++{ ++ HRESULT OpenDSObject([in] BSTR path, [in] BSTR user, [in] BSTR password, [in] long reserved, [out,retval] IDispatch **obj); ++} ++ + /***************************************************************************** + * IADsADSystemInfo interface + */ +-- +2.20.1 + diff --git a/patches/activeds-ADsOpenObject/0003-adsldp-Add-LDAPNamespace-stubs.patch b/patches/activeds-ADsOpenObject/0003-adsldp-Add-LDAPNamespace-stubs.patch new file mode 100644 index 00000000..d072cff7 --- /dev/null +++ b/patches/activeds-ADsOpenObject/0003-adsldp-Add-LDAPNamespace-stubs.patch @@ -0,0 +1,483 @@ +From ba1eb1310db57db3820a3886e374afc507c2b507 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Tue, 19 Nov 2019 11:34:13 +0800 +Subject: [PATCH 3/5] adsldp: Add LDAPNamespace stubs. +Content-Type: text/plain; charset=UTF-8 +To: wine-devel@winehq.org + +Signed-off-by: Dmitry Timoshkov +--- + dlls/adsldp/Makefile.in | 5 +- + dlls/adsldp/adsldp.c | 295 ++++++++++++++++++++++++++++++++++++---- + dlls/adsldp/adsldp.idl | 9 ++ + dlls/adsldp/adsldp.rgs | 16 +++ + dlls/adsldp/rsrc.rc | 20 +++ + 5 files changed, 319 insertions(+), 26 deletions(-) + create mode 100644 dlls/adsldp/adsldp.rgs + create mode 100644 dlls/adsldp/rsrc.rc + +diff --git a/dlls/adsldp/Makefile.in b/dlls/adsldp/Makefile.in +index 4dce14fd0d..7bf07fce2c 100644 +--- a/dlls/adsldp/Makefile.in ++++ b/dlls/adsldp/Makefile.in +@@ -1,10 +1,13 @@ + MODULE = adsldp.dll +-IMPORTS = oleaut32 secur32 ++IMPORTS = oleaut32 secur32 rpcrt4 + + EXTRADLLFLAGS = -mno-cygwin ++dlldata_EXTRADEFS = -DENTRY_PREFIX=ADSLDP_ + + C_SRCS = \ + adsldp.c + + IDL_SRCS = \ + adsldp.idl ++ ++RC_SRCS = rsrc.rc +diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c +index 4fc0de41eb..ef62aad279 100644 +--- a/dlls/adsldp/adsldp.c ++++ b/dlls/adsldp/adsldp.c +@@ -31,10 +31,15 @@ + #define SECURITY_WIN32 + #include "security.h" + ++#include "wine/heap.h" + #include "wine/debug.h" + + WINE_DEFAULT_DEBUG_CHANNEL(adsldp); + ++DEFINE_GUID(CLSID_LDAPNamespace,0x228d9a82,0xc302,0x11cf,0x9a,0xa4,0x00,0xaa,0x00,0x4a,0x56,0x91); ++ ++extern HRESULT WINAPI ADSLDP_DllGetClassObject(REFCLSID,REFIID,void **) DECLSPEC_HIDDEN; ++ + static HMODULE adsldp_hinst; + + typedef struct +@@ -235,31 +240,239 @@ static const IADsADSystemInfoVtbl IADsADSystemInfo_vtbl = + sysinfo_GetTrees + }; + +-static HRESULT ADSystemInfo_create(void **obj) ++static HRESULT ADSystemInfo_create(REFIID riid, void **obj) + { + AD_sysinfo *sysinfo; ++ HRESULT hr; + + sysinfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*sysinfo)); + if (!sysinfo) return E_OUTOFMEMORY; + + sysinfo->IADsADSystemInfo_iface.lpVtbl = &IADsADSystemInfo_vtbl; + sysinfo->ref = 1; +- *obj = &sysinfo->IADsADSystemInfo_iface; + +- TRACE("created %p\n", *obj); ++ hr = IADsADSystemInfo_QueryInterface(&sysinfo->IADsADSystemInfo_iface, riid, obj); ++ IADsADSystemInfo_Release(&sysinfo->IADsADSystemInfo_iface); + +- return S_OK; ++ return hr; + } + ++typedef struct ++{ ++ IADs IADs_iface; ++ LONG ref; ++} LDAP_namespace; ++ ++static inline LDAP_namespace *impl_from_IADs(IADs *iface) ++{ ++ return CONTAINING_RECORD(iface, LDAP_namespace, IADs_iface); ++} ++ ++static HRESULT WINAPI ldapns_QueryInterface(IADs *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_IDispatch) || ++ IsEqualGUID(riid, &IID_IADs)) ++ { ++ IADs_AddRef(iface); ++ *obj = iface; ++ return S_OK; ++ } ++ ++ FIXME("interface %s is not implemented\n", debugstr_guid(riid)); ++ return E_NOINTERFACE; ++} ++ ++static ULONG WINAPI ldapns_AddRef(IADs *iface) ++{ ++ LDAP_namespace *ldap = impl_from_IADs(iface); ++ return InterlockedIncrement(&ldap->ref); ++} ++ ++static ULONG WINAPI ldapns_Release(IADs *iface) ++{ ++ LDAP_namespace *ldap = impl_from_IADs(iface); ++ LONG ref = InterlockedDecrement(&ldap->ref); ++ ++ if (!ref) ++ { ++ TRACE("destroying %p\n", iface); ++ HeapFree(GetProcessHeap(), 0, ldap); ++ } ++ ++ return ref; ++} ++ ++static HRESULT WINAPI ldapns_GetTypeInfoCount(IADs *iface, UINT *count) ++{ ++ FIXME("%p,%p: stub\n", iface, count); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_GetTypeInfo(IADs *iface, UINT index, LCID lcid, ITypeInfo **info) ++{ ++ FIXME("%p,%u,%#x,%p: stub\n", iface, index, lcid, info); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_GetIDsOfNames(IADs *iface, REFIID riid, LPOLESTR *names, ++ UINT count, LCID lcid, DISPID *dispid) ++{ ++ FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_Invoke(IADs *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, ++ DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) ++{ ++ FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags, ++ params, result, excepinfo, argerr); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_get_Name(IADs *iface, BSTR *retval) ++{ ++ FIXME("%p,%p: stub\n", iface, retval); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_get_Class(IADs *iface, BSTR *retval) ++{ ++ FIXME("%p,%p: stub\n", iface, retval); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_get_GUID(IADs *iface, BSTR *retval) ++{ ++ FIXME("%p,%p: stub\n", iface, retval); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_get_ADsPath(IADs *iface, BSTR *retval) ++{ ++ FIXME("%p,%p: stub\n", iface, retval); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_get_Parent(IADs *iface, BSTR *retval) ++{ ++ FIXME("%p,%p: stub\n", iface, retval); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_get_Schema(IADs *iface, BSTR *retval) ++{ ++ FIXME("%p,%p: stub\n", iface, retval); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_GetInfo(IADs *iface) ++{ ++ FIXME("%p: stub\n", iface); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_SetInfo(IADs *iface) ++{ ++ FIXME("%p: stub\n", iface); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_Get(IADs *iface, BSTR name, VARIANT *prop) ++{ ++ FIXME("%p,%s,%p: stub\n", iface, debugstr_w(name), prop); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_Put(IADs *iface, BSTR name, VARIANT prop) ++{ ++ FIXME("%p,%s,%s: stub\n", iface, debugstr_w(name), wine_dbgstr_variant(&prop)); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_GetEx(IADs *iface, BSTR name, VARIANT *prop) ++{ ++ FIXME("%p,%s,%p: stub\n", iface, debugstr_w(name), prop); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_PutEx(IADs *iface, LONG code, BSTR name, VARIANT prop) ++{ ++ FIXME("%p,%d,%s,%s: stub\n", iface, code, debugstr_w(name), wine_dbgstr_variant(&prop)); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ldapns_GetInfoEx(IADs *iface, VARIANT prop, LONG reserved) ++{ ++ FIXME("%p,%s,%d: stub\n", iface, wine_dbgstr_variant(&prop), reserved); ++ return E_NOTIMPL; ++} ++ ++static const IADsVtbl IADs_vtbl = ++{ ++ ldapns_QueryInterface, ++ ldapns_AddRef, ++ ldapns_Release, ++ ldapns_GetTypeInfoCount, ++ ldapns_GetTypeInfo, ++ ldapns_GetIDsOfNames, ++ ldapns_Invoke, ++ ldapns_get_Name, ++ ldapns_get_Class, ++ ldapns_get_GUID, ++ ldapns_get_ADsPath, ++ ldapns_get_Parent, ++ ldapns_get_Schema, ++ ldapns_GetInfo, ++ ldapns_SetInfo, ++ ldapns_Get, ++ ldapns_Put, ++ ldapns_GetEx, ++ ldapns_PutEx, ++ ldapns_GetInfoEx ++}; ++ ++static HRESULT LDAPNamespace_create(REFIID riid, void **obj) ++{ ++ LDAP_namespace *ldap; ++ HRESULT hr; ++ ++ ldap = heap_alloc(sizeof(*ldap)); ++ if (!ldap) return E_OUTOFMEMORY; ++ ++ ldap->IADs_iface.lpVtbl = &IADs_vtbl; ++ ldap->ref = 1; ++ ++ hr = IADs_QueryInterface(&ldap->IADs_iface, riid, obj); ++ IADs_Release(&ldap->IADs_iface); ++ ++ return hr; ++} ++ ++static const struct class_info ++{ ++ const CLSID *clsid; ++ HRESULT (*constructor)(REFIID, void **); ++} class_info[] = ++{ ++ { &CLSID_ADSystemInfo, ADSystemInfo_create }, ++ { &CLSID_LDAPNamespace, LDAPNamespace_create }, ++}; ++ + typedef struct + { + IClassFactory IClassFactory_iface; +- HRESULT (*constructor)(void **); +-} ADSystemInfo_factory; ++ LONG ref; ++ const struct class_info *info; ++} class_factory; + +-static inline ADSystemInfo_factory *impl_from_IClassFactory(IClassFactory *iface) ++static inline class_factory *impl_from_IClassFactory(IClassFactory *iface) + { +- return CONTAINING_RECORD(iface, ADSystemInfo_factory, IClassFactory_iface); ++ return CONTAINING_RECORD(iface, class_factory, IClassFactory_iface); + } + + static HRESULT WINAPI factory_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *obj) +@@ -283,19 +496,30 @@ static HRESULT WINAPI factory_QueryInterface(IClassFactory *iface, REFIID riid, + + static ULONG WINAPI factory_AddRef(IClassFactory *iface) + { +- return 2; ++ class_factory *factory = impl_from_IClassFactory(iface); ++ ULONG ref = InterlockedIncrement(&factory->ref); ++ ++ TRACE("(%p) ref %u\n", iface, ref); ++ ++ return ref; + } + + static ULONG WINAPI factory_Release(IClassFactory *iface) + { +- return 1; ++ class_factory *factory = impl_from_IClassFactory(iface); ++ ULONG ref = InterlockedDecrement(&factory->ref); ++ ++ TRACE("(%p) ref %u\n", iface, ref); ++ ++ if (!ref) ++ heap_free(factory); ++ ++ return ref; + } + + static HRESULT WINAPI factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj) + { +- ADSystemInfo_factory *factory = impl_from_IClassFactory(iface); +- IUnknown *unknown; +- HRESULT hr; ++ class_factory *factory = impl_from_IClassFactory(iface); + + TRACE("%p,%s,%p\n", outer, debugstr_guid(riid), obj); + +@@ -304,13 +528,7 @@ static HRESULT WINAPI factory_CreateInstance(IClassFactory *iface, IUnknown *out + *obj = NULL; + if (outer) return CLASS_E_NOAGGREGATION; + +- hr = factory->constructor((void **)&unknown); +- if (hr == S_OK) +- { +- hr = IUnknown_QueryInterface(unknown, riid, obj); +- IUnknown_Release(unknown); +- } +- return hr; ++ return factory->info->constructor(riid, obj); + } + + static HRESULT WINAPI factory_LockServer(IClassFactory *iface, BOOL lock) +@@ -328,21 +546,48 @@ static const struct IClassFactoryVtbl factory_vtbl = + factory_LockServer + }; + +-static ADSystemInfo_factory ADSystemInfo_cf = { { &factory_vtbl }, ADSystemInfo_create }; ++static HRESULT factory_constructor(const struct class_info *info, REFIID riid, void **obj) ++{ ++ class_factory *factory; ++ HRESULT hr; ++ ++ factory = heap_alloc(sizeof(*factory)); ++ if (!factory) return E_OUTOFMEMORY; ++ ++ factory->IClassFactory_iface.lpVtbl = &factory_vtbl; ++ factory->ref = 1; ++ factory->info = info; ++ ++ hr = IClassFactory_QueryInterface(&factory->IClassFactory_iface, riid, obj); ++ IClassFactory_Release(&factory->IClassFactory_iface); ++ ++ return hr; ++} + + 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); + + if (!clsid || !iid || !obj) return E_INVALIDARG; + + *obj = NULL; + +- if (IsEqualGUID(clsid, &CLSID_ADSystemInfo)) +- return IClassFactory_QueryInterface(&ADSystemInfo_cf.IClassFactory_iface, iid, obj); ++ for (i = 0; i < ARRAY_SIZE(class_info); i++) ++ { ++ if (IsEqualCLSID(class_info[i].clsid, clsid)) ++ { ++ info = &class_info[i]; ++ break; ++ } ++ } ++ ++ 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; ++ return ADSLDP_DllGetClassObject(clsid, iid, obj); + } + + HRESULT WINAPI DllCanUnloadNow(void) +diff --git a/dlls/adsldp/adsldp.idl b/dlls/adsldp/adsldp.idl +index c2f7504d0c..634aa36327 100644 +--- a/dlls/adsldp/adsldp.idl ++++ b/dlls/adsldp/adsldp.idl +@@ -18,8 +18,17 @@ + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + ++#pragma makedep proxy + #pragma makedep register + ++[ ++ helpstring("LDAP Namespace Object"), ++ progid("LDAPNamespace"), ++ uuid(228d9a82-c302-11cf-9aa4-00aa004a5691), ++ threading(both) ++] ++coclass ADs { } ++ + [ + helpstring("AD System Info Object"), + uuid(50b6327f-afd1-11d2-9cb9-0000f87a369e), +diff --git a/dlls/adsldp/adsldp.rgs b/dlls/adsldp/adsldp.rgs +new file mode 100644 +index 0000000000..0da0946832 +--- /dev/null ++++ b/dlls/adsldp/adsldp.rgs +@@ -0,0 +1,16 @@ ++HKLM ++{ ++ NoRemove Software ++ { ++ NoRemove Microsoft ++ { ++ NoRemove ADs ++ { ++ NoRemove Providers ++ { ++ ForceRemove 'LDAP' = s 'LDAPNamespace' ++ } ++ } ++ } ++ } ++} +diff --git a/dlls/adsldp/rsrc.rc b/dlls/adsldp/rsrc.rc +new file mode 100644 +index 0000000000..914fe0b2f3 +--- /dev/null ++++ b/dlls/adsldp/rsrc.rc +@@ -0,0 +1,20 @@ ++/* ++ * Copyright 2019 Dmitry Timoshkov ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++/* @makedep: adsldp.rgs */ ++1 WINE_REGISTRY adsldp.rgs +-- +2.20.1 + diff --git a/patches/activeds-ADsOpenObject/0004-adsldp-Add-IADsOpenDSObject-stubs.patch b/patches/activeds-ADsOpenObject/0004-adsldp-Add-IADsOpenDSObject-stubs.patch new file mode 100644 index 00000000..a836a745 --- /dev/null +++ b/patches/activeds-ADsOpenObject/0004-adsldp-Add-IADsOpenDSObject-stubs.patch @@ -0,0 +1,156 @@ +From 73b97a7095f833e5323117c1acbb8a64c5e3afcb Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Tue, 19 Nov 2019 11:46:50 +0800 +Subject: [PATCH 4/5] adsldp: Add IADsOpenDSObject stubs. +Content-Type: text/plain; charset=UTF-8 +To: wine-devel@winehq.org + +Signed-off-by: Dmitry Timoshkov +--- + dlls/adsldp/adsldp.c | 102 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 102 insertions(+) + +diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c +index ef62aad279..bdce30c143 100644 +--- a/dlls/adsldp/adsldp.c ++++ b/dlls/adsldp/adsldp.c +@@ -260,6 +260,7 @@ static HRESULT ADSystemInfo_create(REFIID riid, void **obj) + typedef struct + { + IADs IADs_iface; ++ IADsOpenDSObject IADsOpenDSObject_iface; + LONG ref; + } LDAP_namespace; + +@@ -270,6 +271,8 @@ static inline LDAP_namespace *impl_from_IADs(IADs *iface) + + static HRESULT WINAPI ldapns_QueryInterface(IADs *iface, REFIID riid, void **obj) + { ++ LDAP_namespace *ldap = impl_from_IADs(iface); ++ + TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); + + if (!riid || !obj) return E_INVALIDARG; +@@ -283,6 +286,13 @@ static HRESULT WINAPI ldapns_QueryInterface(IADs *iface, REFIID riid, void **obj + return S_OK; + } + ++ if (IsEqualGUID(riid, &IID_IADsOpenDSObject)) ++ { ++ IADs_AddRef(iface); ++ *obj = &ldap->IADsOpenDSObject_iface; ++ return S_OK; ++ } ++ + FIXME("interface %s is not implemented\n", debugstr_guid(riid)); + return E_NOINTERFACE; + } +@@ -436,6 +446,97 @@ static const IADsVtbl IADs_vtbl = + ldapns_GetInfoEx + }; + ++static inline LDAP_namespace *impl_from_IADsOpenDSObject(IADsOpenDSObject *iface) ++{ ++ return CONTAINING_RECORD(iface, LDAP_namespace, IADsOpenDSObject_iface); ++} ++ ++static HRESULT WINAPI openobj_QueryInterface(IADsOpenDSObject *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_IADsOpenDSObject) || ++ IsEqualGUID(riid, &IID_IDispatch) || ++ IsEqualGUID(riid, &IID_IUnknown)) ++ { ++ IADsOpenDSObject_AddRef(iface); ++ *obj = iface; ++ return S_OK; ++ } ++ ++ FIXME("interface %s is not implemented\n", debugstr_guid(riid)); ++ return E_NOINTERFACE; ++} ++ ++static ULONG WINAPI openobj_AddRef(IADsOpenDSObject *iface) ++{ ++ LDAP_namespace *ldap = impl_from_IADsOpenDSObject(iface); ++ return InterlockedIncrement(&ldap->ref); ++} ++ ++static ULONG WINAPI openobj_Release(IADsOpenDSObject *iface) ++{ ++ LDAP_namespace *ldap = impl_from_IADsOpenDSObject(iface); ++ LONG ref = InterlockedDecrement(&ldap->ref); ++ ++ if (!ref) ++ { ++ TRACE("destroying %p\n", iface); ++ HeapFree(GetProcessHeap(), 0, ldap); ++ } ++ ++ return ref; ++} ++ ++static HRESULT WINAPI openobj_GetTypeInfoCount(IADsOpenDSObject *iface, UINT *count) ++{ ++ FIXME("%p,%p: stub\n", iface, count); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI openobj_GetTypeInfo(IADsOpenDSObject *iface, UINT index, LCID lcid, ITypeInfo **info) ++{ ++ FIXME("%p,%u,%#x,%p: stub\n", iface, index, lcid, info); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI openobj_GetIDsOfNames(IADsOpenDSObject *iface, REFIID riid, LPOLESTR *names, ++ UINT count, LCID lcid, DISPID *dispid) ++{ ++ FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI openobj_Invoke(IADsOpenDSObject *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, ++ DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) ++{ ++ FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags, ++ params, result, excepinfo, argerr); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, BSTR user, BSTR password, ++ LONG reserved, IDispatch **obj) ++{ ++ FIXME("%p,%s,%s,%s,%d,%p: stub\n", iface, debugstr_w(path), debugstr_w(user), debugstr_w(password), ++ reserved, obj); ++ return E_NOTIMPL; ++} ++ ++static const IADsOpenDSObjectVtbl IADsOpenDSObject_vtbl = ++{ ++ openobj_QueryInterface, ++ openobj_AddRef, ++ openobj_Release, ++ openobj_GetTypeInfoCount, ++ openobj_GetTypeInfo, ++ openobj_GetIDsOfNames, ++ openobj_Invoke, ++ openobj_OpenDSObject ++}; ++ + static HRESULT LDAPNamespace_create(REFIID riid, void **obj) + { + LDAP_namespace *ldap; +@@ -445,6 +546,7 @@ static HRESULT LDAPNamespace_create(REFIID riid, void **obj) + if (!ldap) return E_OUTOFMEMORY; + + ldap->IADs_iface.lpVtbl = &IADs_vtbl; ++ ldap->IADsOpenDSObject_iface.lpVtbl = &IADsOpenDSObject_vtbl; + ldap->ref = 1; + + hr = IADs_QueryInterface(&ldap->IADs_iface, riid, obj); +-- +2.20.1 + diff --git a/patches/activeds-ADsOpenObject/0005-adsldp-tests-Add-some-tests-for-LDAPNamespace.patch b/patches/activeds-ADsOpenObject/0005-adsldp-tests-Add-some-tests-for-LDAPNamespace.patch new file mode 100644 index 00000000..6d48f9b2 --- /dev/null +++ b/patches/activeds-ADsOpenObject/0005-adsldp-tests-Add-some-tests-for-LDAPNamespace.patch @@ -0,0 +1,123 @@ +From 488afac28472b0563c67cfad8c02a82f489c2c04 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Tue, 19 Nov 2019 12:12:27 +0800 +Subject: [PATCH 5/5] adsldp/tests: Add some tests for LDAPNamespace. +Content-Type: text/plain; charset=UTF-8 +To: wine-devel@winehq.org + +Signed-off-by: Dmitry Timoshkov +--- + dlls/adsldp/tests/Makefile.in | 1 + + dlls/adsldp/tests/ldap.c | 78 +++++++++++++++++++++++++++++++++++ + dlls/adsldp/tests/sysinfo.c | 2 + + 3 files changed, 81 insertions(+) + create mode 100644 dlls/adsldp/tests/ldap.c + +diff --git a/dlls/adsldp/tests/Makefile.in b/dlls/adsldp/tests/Makefile.in +index 777d2aa9de..52141139d5 100644 +--- a/dlls/adsldp/tests/Makefile.in ++++ b/dlls/adsldp/tests/Makefile.in +@@ -2,4 +2,5 @@ TESTDLL = adsldp.dll + IMPORTS = ole32 oleaut32 secur32 advapi32 uuid + + C_SRCS = \ ++ ldap.c \ + sysinfo.c +diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c +new file mode 100644 +index 0000000000..36b128da20 +--- /dev/null ++++ b/dlls/adsldp/tests/ldap.c +@@ -0,0 +1,78 @@ ++/* ++ * LDAPNamespace Tests ++ * ++ * Copyright 2019 Dmitry Timoshkov ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#include ++#include ++ ++#define COBJMACROS ++ ++#include "windef.h" ++#include "winbase.h" ++#include "objbase.h" ++#include "iads.h" ++ ++#include "wine/test.h" ++ ++#include "initguid.h" ++DEFINE_GUID(CLSID_LDAPNamespace,0x228d9a82,0xc302,0x11cf,0x9a,0xa4,0x00,0xaa,0x00,0x4a,0x56,0x91); ++ ++static void test_LDAP(void) ++{ ++ HRESULT hr; ++ IUnknown *unk; ++ IADs *ads; ++ IADsOpenDSObject *ads_open; ++ IDispatch *disp; ++ ++ hr = CoCreateInstance(&CLSID_LDAPNamespace, 0, CLSCTX_INPROC_SERVER, &IID_IADs, (void **)&ads); ++ ok(hr == S_OK, "got %#x\n", hr); ++ IADs_Release(ads); ++ ++ hr = CoCreateInstance(&CLSID_LDAPNamespace, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); ++ ok(hr == S_OK, "got %#x\n", hr); ++ ++ hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void **)&disp); ++ ok(hr == S_OK, "got %#x\n", hr); ++ IDispatch_Release(disp); ++ ++ hr = IUnknown_QueryInterface(unk, &IID_IADsOpenDSObject, (void **)&ads_open); ++ ok(hr == S_OK, "got %#x\n", hr); ++ IADsOpenDSObject_Release(ads_open); ++ ++ hr = IADsOpenDSObject_OpenDSObject(ads_open, (BSTR)L"LDAP:", NULL, NULL, ADS_SECURE_AUTHENTICATION, &disp); ++todo_wine ++ ok(hr == S_OK, "got %#x\n", hr); ++if (hr == S_OK) ++ IDispatch_Release(disp); ++ ++ IUnknown_Release(unk); ++} ++ ++START_TEST(ldap) ++{ ++ HRESULT hr; ++ ++ hr = CoInitialize(NULL); ++ ok(hr == S_OK, "got %#x\n", hr); ++ ++ test_LDAP(); ++ ++ CoUninitialize(); ++} +diff --git a/dlls/adsldp/tests/sysinfo.c b/dlls/adsldp/tests/sysinfo.c +index db982aa82f..cb250190f1 100644 +--- a/dlls/adsldp/tests/sysinfo.c ++++ b/dlls/adsldp/tests/sysinfo.c +@@ -216,4 +216,6 @@ START_TEST(sysinfo) + test_ComputerName(); + test_UserName(); + test_sysinfo(); ++ ++ CoUninitialize(); + } +-- +2.20.1 + diff --git a/patches/activeds-ADsOpenObject/definition b/patches/activeds-ADsOpenObject/definition new file mode 100644 index 00000000..c9e4ccef --- /dev/null +++ b/patches/activeds-ADsOpenObject/definition @@ -0,0 +1,2 @@ +Fixes: [40649] activeds: Implement ADsOpenObject. +#Fixes: [42885] ADsOpenObject to bind to user's account/computer. (related) diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 8bdd7e45..91c3e976 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -86,6 +86,7 @@ patch_enable_all () enable_Compiler_Warnings="$1" enable_Pipelight="$1" enable_Staging="$1" + enable_activeds_ADsOpenObject="$1" enable_advapi32_CreateRestrictedToken="$1" enable_advapi32_LsaLookupPrivilegeName="$1" enable_advapi32_LsaLookupSids="$1" @@ -384,6 +385,9 @@ patch_enable () Staging) enable_Staging="$2" ;; + activeds-ADsOpenObject) + enable_activeds_ADsOpenObject="$2" + ;; advapi32-CreateRestrictedToken) enable_advapi32_CreateRestrictedToken="$2" ;; @@ -2115,6 +2119,31 @@ if test "$enable_Staging" -eq 1; then ) >> "$patchlist" fi +# Patchset activeds-ADsOpenObject +# | +# | This patchset fixes the following Wine bugs: +# | * [#40649] activeds: Implement ADsOpenObject. +# | +# | Modified files: +# | * dlls/activeds/Makefile.in, dlls/activeds/activeds_main.c, dlls/adsldp/Makefile.in, dlls/adsldp/adsldp.c, +# | dlls/adsldp/adsldp.idl, dlls/adsldp/adsldp.rgs, dlls/adsldp/rsrc.rc, dlls/adsldp/tests/Makefile.in, +# | dlls/adsldp/tests/ldap.c, dlls/adsldp/tests/sysinfo.c, include/adserr.h, include/iads.idl +# | +if test "$enable_activeds_ADsOpenObject" -eq 1; then + patch_apply activeds-ADsOpenObject/0001-include-Add-adserr.h.patch + patch_apply activeds-ADsOpenObject/0002-activeds-Implement-ADsOpenObject.patch + patch_apply activeds-ADsOpenObject/0003-adsldp-Add-LDAPNamespace-stubs.patch + patch_apply activeds-ADsOpenObject/0004-adsldp-Add-IADsOpenDSObject-stubs.patch + patch_apply activeds-ADsOpenObject/0005-adsldp-tests-Add-some-tests-for-LDAPNamespace.patch + ( + printf '%s\n' '+ { "Dmitry Timoshkov", "include: Add adserr.h.", 1 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "activeds: Implement ADsOpenObject.", 1 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "adsldp: Add LDAPNamespace stubs.", 1 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "adsldp: Add IADsOpenDSObject stubs.", 1 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "adsldp/tests: Add some tests for LDAPNamespace.", 1 },'; + ) >> "$patchlist" +fi + # Patchset advapi32-CreateRestrictedToken # | # | This patchset fixes the following Wine bugs: