summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2018-04-28 09:16:15 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2018-05-02 16:38:40 +0200
commitf154f63cb662f02415d5cb0051011bdb5d0d523c (patch)
tree31f22312e0c8ab339cdbb132a82da08b52f15dd0
parentea1f50894ac3e681213b874af08217ae25d0433a (diff)
WinUserInfoBe: a new config backend for user data provided by Windows
This backend provides Active Directory details for current user. If the system is not part of Active Directory domain, GetUserNameEx is used instead, so at least user (given) name is configured. Unlike ldap backend, this one doesn't need connection configuration, as the used API works with current user security context. Change-Id: I74bcc79591a658dc5121df1f09caa15d272fbe12 Reviewed-on: https://gerrit.libreoffice.org/53590 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--Repository.mk1
-rw-r--r--extensions/Library_WinUserInfoBe.mk38
-rw-r--r--extensions/Module_extensions.mk1
-rw-r--r--extensions/source/config/WinUserInfo/WinUserInfoBe.component15
-rw-r--r--extensions/source/config/WinUserInfo/WinUserInfoBe.cxx479
-rw-r--r--extensions/source/config/WinUserInfo/WinUserInfoBe.hxx115
-rw-r--r--extensions/source/config/WinUserInfo/componentdef.cxx35
-rw-r--r--officecfg/Package_misc.mk3
-rw-r--r--officecfg/registry/schema/oo-winuser.xcd.sample95
-rw-r--r--officecfg/registry/schema/org/openoffice/UserProfile.xcs11
-rw-r--r--postprocess/Rdb_services.mk3
11 files changed, 796 insertions, 0 deletions
diff --git a/Repository.mk b/Repository.mk
index 6ef05911a1bd..e4a11d3d160f 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -391,6 +391,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \
icg \
$(if $(ENABLE_JAVA),jdbc) \
ldapbe2 \
+ $(if $(filter WNT,$(OS)),WinUserInfoBe) \
localebe1 \
log \
lng \
diff --git a/extensions/Library_WinUserInfoBe.mk b/extensions/Library_WinUserInfoBe.mk
new file mode 100644
index 000000000000..6fdad389a480
--- /dev/null
+++ b/extensions/Library_WinUserInfoBe.mk
@@ -0,0 +1,38 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#
+
+$(eval $(call gb_Library_Library,WinUserInfoBe))
+
+$(eval $(call gb_Library_set_componentfile,WinUserInfoBe,extensions/source/config/WinUserInfo/WinUserInfoBe))
+
+$(eval $(call gb_Library_use_sdk_api,WinUserInfoBe))
+
+$(eval $(call gb_Library_add_exception_objects,WinUserInfoBe,\
+ extensions/source/config/WinUserInfo/componentdef \
+ extensions/source/config/WinUserInfo/WinUserInfoBe \
+))
+
+$(eval $(call gb_Library_use_libraries,WinUserInfoBe,\
+ comphelper \
+ cppuhelper \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_Library_use_system_win32_libs,WinUserInfoBe,\
+ Ole32 \
+ OleAut32 \
+ Activeds \
+ Adsiid \
+ Secur32 \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/extensions/Module_extensions.mk b/extensions/Module_extensions.mk
index 3ab21f58a411..31512ff4045f 100644
--- a/extensions/Module_extensions.mk
+++ b/extensions/Module_extensions.mk
@@ -17,6 +17,7 @@ ifneq ($(filter-out IOS ANDROID,$(OS)),)
$(eval $(call gb_Module_add_targets,extensions,\
Library_abp \
Library_ldapbe2 \
+ $(if $(filter WNT,$(OS)),Library_WinUserInfoBe) \
Library_log \
Library_scn \
UIConfig_sabpilot \
diff --git a/extensions/source/config/WinUserInfo/WinUserInfoBe.component b/extensions/source/config/WinUserInfo/WinUserInfoBe.component
new file mode 100644
index 000000000000..90c3e0060685
--- /dev/null
+++ b/extensions/source/config/WinUserInfo/WinUserInfoBe.component
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ prefix="WinUserInfoBe" xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.configuration.backend.WinUserInfoBe">
+ <service name="com.sun.star.configuration.backend.WinUserInfoBe"/>
+ </implementation>
+</component>
diff --git a/extensions/source/config/WinUserInfo/WinUserInfoBe.cxx b/extensions/source/config/WinUserInfo/WinUserInfoBe.cxx
new file mode 100644
index 000000000000..3e60716b5cdd
--- /dev/null
+++ b/extensions/source/config/WinUserInfo/WinUserInfoBe.cxx
@@ -0,0 +1,479 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "WinUserInfoBe.hxx"
+
+#include <com/sun/star/beans/Optional.hpp>
+#include <comphelper/base64.hxx>
+#include <comphelper/configurationhelper.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <map>
+#include <o3tl/make_unique.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+
+#include <Iads.h>
+#include <Adshlp.h>
+#include <Lmcons.h>
+#define SECURITY_WIN32
+#include <Security.h>
+
+namespace extensions
+{
+namespace config
+{
+namespace WinUserInfo
+{
+class WinUserInfoBe_Impl
+{
+public:
+ virtual ~WinUserInfoBe_Impl(){};
+ virtual OUString GetGivenName() = 0;
+ virtual OUString GetSn() { return ""; }
+ virtual OUString GetFathersname() { return ""; }
+ virtual OUString GetInitials() { return ""; }
+ virtual OUString GetStreet() { return ""; }
+ virtual OUString GetCity() { return ""; }
+ virtual OUString GetState() { return ""; }
+ virtual OUString GetApartment() { return ""; }
+ virtual OUString GetPostalCode() { return ""; }
+ virtual OUString GetCountry() { return ""; }
+ virtual OUString GetOrganization() { return ""; }
+ virtual OUString GetPosition() { return ""; }
+ virtual OUString GetTitle() { return ""; }
+ virtual OUString GetHomePhone() { return ""; }
+ virtual OUString GetTelephoneNumber() { return ""; }
+ virtual OUString GetFaxNumber() { return ""; }
+ virtual OUString GetMail() { return ""; }
+};
+}
+}
+}
+
+namespace
+{
+constexpr char givenname[]("givenname");
+constexpr char sn[]("sn");
+constexpr char fathersname[]("fathersname");
+constexpr char initials[]("initials");
+constexpr char street[]("street");
+constexpr char l[]("l");
+constexpr char st[]("st");
+constexpr char apartment[]("apartment");
+constexpr char postalcode[]("postalcode");
+constexpr char c[]("c");
+constexpr char o[]("o");
+constexpr char position[]("position");
+constexpr char title[]("title");
+constexpr char homephone[]("homephone");
+constexpr char telephonenumber[]("telephonenumber");
+constexpr char facsimiletelephonenumber[]("facsimiletelephonenumber");
+constexpr char mail[]("mail");
+
+// Backend class implementing access to Active Directory user data. It caches its encoded data
+// in a configuration entry, to allow reusing it when user later doesn't have access to AD DC
+// (otherwise the user would get different data when connected vs not connected).
+class ADsUserAccess : public extensions::config::WinUserInfo::WinUserInfoBe_Impl
+{
+public:
+ ADsUserAccess(const css::uno::Reference<css::uno::XComponentContext>& xContext)
+ {
+ try
+ {
+ struct CoInitializeGuard
+ {
+ CoInitializeGuard()
+ {
+ if (FAILED(CoInitialize(nullptr)))
+ throw css::uno::RuntimeException();
+ }
+ ~CoInitializeGuard() { CoUninitialize(); }
+ } aCoInitializeGuard;
+
+ IADsADSystemInfo* pADsys;
+ HRESULT hr = CoCreateInstance(CLSID_ADSystemInfo, nullptr, CLSCTX_INPROC_SERVER,
+ IID_IADsADSystemInfo, (void**)&pADsys);
+ if (FAILED(hr))
+ throw css::uno::RuntimeException();
+ CoIfPtr<IADsADSystemInfo> aADsysGuard(pADsys);
+
+ BSTR sUserDN;
+ hr = pADsys->get_UserName(&sUserDN);
+ if (FAILED(hr))
+ throw css::uno::RuntimeException();
+ BSTRGuard aUserNameGuard(sUserDN, SysFreeString);
+ // If this user is an AD user, then without an active connection to the domain, all the
+ // above will succeed, and m_sUserDN will be correctly initialized, but the following
+ // call to ADsGetObject will fail, and we will attempt reading cached values.
+ m_sUserDN = o3tl::toU(sUserDN);
+ OUString sLdapUserDN = "LDAP://" + m_sUserDN;
+ IADsUser* pUser;
+ hr = ADsGetObject(o3tl::toW(sLdapUserDN.getStr()), IID_IADsUser, (void**)&pUser);
+ if (FAILED(hr))
+ throw css::uno::RuntimeException();
+ CoIfPtr<IADsUser> pUserGuard(pUser);
+ // Fetch all the required information right now, when we know to have access to AD
+ // (later the connection may already be lost)
+ m_aMap[givenname] = Str(pUser, &IADsUser::get_FirstName);
+ m_aMap[sn] = Str(pUser, &IADsUser::get_LastName);
+ m_aMap[initials] = Str(pUser, L"initials");
+ m_aMap[street] = Str(pUser, L"streetAddress");
+ m_aMap[l] = Str(pUser, L"l");
+ m_aMap[st] = Str(pUser, L"st");
+ m_aMap[postalcode] = Str(pUser, L"postalCode");
+ m_aMap[c] = Str(pUser, L"co");
+ m_aMap[o] = Str(pUser, L"company");
+ m_aMap[title] = Str(pUser, &IADsUser::get_Title);
+ m_aMap[homephone] = Str(pUser, L"homePhone");
+ m_aMap[telephonenumber] = Str(pUser, L"TelephoneNumber");
+ m_aMap[facsimiletelephonenumber] = Str(pUser, L"facsimileTelephoneNumber");
+ m_aMap[mail] = Str(pUser, &IADsUser::get_EmailAddress);
+
+ CacheData(xContext);
+ }
+ catch (css::uno::Exception&)
+ {
+ // Maybe we temporarily lost connection to AD; try to get cached data
+ GetCachedData(xContext);
+ }
+ }
+ ~ADsUserAccess() {}
+
+ virtual OUString GetGivenName() override { return m_aMap[givenname]; }
+ virtual OUString GetSn() override { return m_aMap[sn]; }
+ virtual OUString GetInitials() override { return m_aMap[initials]; }
+ virtual OUString GetStreet() override { return m_aMap[street]; }
+ virtual OUString GetCity() override { return m_aMap[l]; }
+ virtual OUString GetState() override { return m_aMap[st]; }
+ virtual OUString GetPostalCode() override { return m_aMap[postalcode]; }
+ virtual OUString GetCountry() override { return m_aMap[c]; }
+ virtual OUString GetOrganization() override { return m_aMap[o]; }
+ virtual OUString GetTitle() override { return m_aMap[title]; }
+ virtual OUString GetHomePhone() override { return m_aMap[homephone]; }
+ virtual OUString GetTelephoneNumber() override { return m_aMap[telephonenumber]; }
+ virtual OUString GetFaxNumber() override { return m_aMap[facsimiletelephonenumber]; }
+ virtual OUString GetMail() override { return m_aMap[mail]; }
+
+private:
+ static void ReleaseIUnknown(IUnknown* p)
+ {
+ if (p)
+ p->Release();
+ }
+ template <class If> class CoIfPtr : public std::unique_ptr<If, decltype(&ReleaseIUnknown)>
+ {
+ public:
+ CoIfPtr(If* p = nullptr)
+ : std::unique_ptr<If, decltype(&ReleaseIUnknown)>(p, ReleaseIUnknown)
+ {
+ }
+ };
+ typedef std::unique_ptr<OLECHAR, decltype(&SysFreeString)> BSTRGuard;
+
+ typedef HRESULT (__stdcall IADsUser::*getstrfunc)(BSTR*);
+ static OUString Str(IADsUser* pUser, getstrfunc func)
+ {
+ BSTR sBstr;
+ if (FAILED((pUser->*func)(&sBstr)))
+ return "";
+ BSTRGuard aBstrGuard(sBstr, SysFreeString);
+ return o3tl::toU(sBstr);
+ }
+ static OUString Str(IADsUser* pUser, const wchar_t* property)
+ {
+ BSTRGuard sBstrProp(SysAllocString(property), SysFreeString);
+ struct AutoVariant : public VARIANT
+ {
+ AutoVariant() { VariantInit(this); }
+ ~AutoVariant() { VariantClear(this); }
+ } varArr;
+ if (FAILED(pUser->GetEx(sBstrProp.get(), &varArr)))
+ return "";
+ SAFEARRAY* sa = V_ARRAY(&varArr);
+ LONG nStart, nEnd;
+ if (FAILED(SafeArrayGetLBound(sa, 1, &nStart)) || FAILED(SafeArrayGetUBound(sa, 1, &nEnd)))
+ return "";
+ AutoVariant varItem;
+ for (LONG i = nStart; i <= nEnd; i++)
+ {
+ if (FAILED(SafeArrayGetElement(sa, &i, &varItem)))
+ continue;
+ if (varItem.vt == VT_BSTR)
+ return o3tl::toU(V_BSTR(&varItem));
+ VariantClear(&varItem);
+ }
+ return "";
+ }
+
+ void CacheData(const css::uno::Reference<css::uno::XComponentContext>& xContext)
+ {
+ try
+ {
+ const OUString sNul('\0');
+ OUStringBuffer sCachedData(200);
+ sCachedData.append("user=" + m_sUserDN);
+ sCachedData.append(sNul + givenname + "=" + GetGivenName());
+ sCachedData.append(sNul + sn + "=" + GetSn());
+ sCachedData.append(sNul + initials + "=" + GetInitials());
+ sCachedData.append(sNul + street + "=" + GetStreet());
+ sCachedData.append(sNul + l + "=" + GetCity());
+ sCachedData.append(sNul + st + "=" + GetState());
+ sCachedData.append(sNul + postalcode + "=" + GetPostalCode());
+ sCachedData.append(sNul + c + "=" + GetCountry());
+ sCachedData.append(sNul + o + "=" + GetOrganization());
+ sCachedData.append(sNul + title + "=" + GetTitle());
+ sCachedData.append(sNul + homephone + "=" + GetHomePhone());
+ sCachedData.append(sNul + telephonenumber + "=" + GetTelephoneNumber());
+ sCachedData.append(sNul + facsimiletelephonenumber + "=" + GetFaxNumber());
+ sCachedData.append(sNul + mail + "=" + GetMail());
+ const css::uno::Sequence<sal_Int8> seqCachedData(
+ reinterpret_cast<const sal_Int8*>(sCachedData.getStr()),
+ sCachedData.getLength() * sizeof(sal_Unicode));
+ OUStringBuffer sOutBuf;
+ comphelper::Base64::encode(sOutBuf, seqCachedData);
+
+ auto xIface = comphelper::ConfigurationHelper::openConfig(
+ xContext, "org.openoffice.UserProfile/WinUserInfo",
+ comphelper::EConfigurationModes::Standard);
+ css::uno::Reference<css::container::XNameReplace> xNameReplace(
+ xIface, css::uno::UNO_QUERY_THROW);
+ xNameReplace->replaceByName("Cache", css::uno::makeAny(sOutBuf.makeStringAndClear()));
+
+ css::uno::Reference<css::util::XChangesBatch> xChangesBatch(xIface,
+ css::uno::UNO_QUERY_THROW);
+ xChangesBatch->commitChanges();
+ }
+ catch (const css::uno::Exception& e)
+ {
+ SAL_WARN("extensions.config",
+ "ADsUserAccess: access to configuration data failed: " << e);
+ }
+ }
+
+ void GetCachedData(const css::uno::Reference<css::uno::XComponentContext>& xContext)
+ {
+ if (m_sUserDN.isEmpty())
+ throw css::uno::RuntimeException();
+
+ auto xIface = comphelper::ConfigurationHelper::openConfig(
+ xContext, "org.openoffice.UserProfile/WinUserInfo",
+ comphelper::EConfigurationModes::ReadOnly);
+ css::uno::Reference<css::container::XNameAccess> xNameAccess(xIface,
+ css::uno::UNO_QUERY_THROW);
+ OUString sCache;
+ xNameAccess->getByName("Cache") >>= sCache;
+ if (sCache.isEmpty())
+ throw css::uno::RuntimeException();
+
+ {
+ css::uno::Sequence<sal_Int8> seqCachedData;
+ comphelper::Base64::decode(seqCachedData, sCache);
+ sCache = OUString(reinterpret_cast<const sal_Unicode*>(seqCachedData.getConstArray()),
+ seqCachedData.getLength() / sizeof(sal_Unicode));
+ }
+
+ OUString sUserDN;
+ std::map<const OUString, OUString> aMap;
+ sal_Int32 nIndex = 0;
+ do
+ {
+ const OUString sEntry = sCache.getToken(0, '\0', nIndex);
+ sal_Int32 nEqIndex = 0;
+ const OUString sEntryName = sEntry.getToken(0, '=', nEqIndex);
+ OUString sEntryVal;
+ if (nEqIndex >= 0)
+ sEntryVal = sEntry.copy(nEqIndex);
+ if (sEntryName == "user")
+ sUserDN = sEntryVal;
+ else
+ aMap[sEntryName] = sEntryVal;
+ } while (nIndex >= 0);
+
+ if (sUserDN != m_sUserDN)
+ throw css::uno::RuntimeException();
+ m_aMap = std::move(aMap);
+ }
+
+ OUString m_sUserDN; // used to check if the cached data is for current user
+ std::map<const OUString, OUString> m_aMap;
+};
+
+class SysInfoUserAccess : public extensions::config::WinUserInfo::WinUserInfoBe_Impl
+{
+public:
+ SysInfoUserAccess()
+ {
+ try
+ {
+ ULONG nSize = 0;
+ GetUserNameExW(NameDisplay, nullptr, &nSize);
+ if (GetLastError() != ERROR_MORE_DATA)
+ throw css::uno::RuntimeException();
+ auto pNameBuf(o3tl::make_unique<wchar_t[]>(nSize));
+ if (!GetUserNameExW(NameDisplay, pNameBuf.get(), &nSize))
+ throw css::uno::RuntimeException();
+ m_sName = o3tl::toU(pNameBuf.get());
+ }
+ catch (css::uno::RuntimeException&)
+ {
+ // GetUserNameEx may fail in some cases (e.g., for built-in AD domain
+ // administrator account on non-DC systems), where GetUserName will
+ // still give a name.
+ DWORD nSize = UNLEN + 1;
+ auto pNameBuf(o3tl::make_unique<wchar_t[]>(nSize));
+ if (!GetUserNameW(pNameBuf.get(), &nSize))
+ throw css::uno::RuntimeException();
+ m_sName = o3tl::toU(pNameBuf.get());
+ }
+ }
+
+ virtual OUString GetGivenName() override { return m_sName; }
+
+private:
+ OUString m_sName;
+};
+}
+
+namespace extensions
+{
+namespace config
+{
+namespace WinUserInfo
+{
+WinUserInfoBe::WinUserInfoBe(const css::uno::Reference<css::uno::XComponentContext>& xContext)
+ : WinUserInfoMutexHolder()
+ , BackendBase(mMutex)
+{
+ try
+ {
+ m_pImpl.reset(new ADsUserAccess(xContext));
+ }
+ catch (css::uno::RuntimeException&)
+ {
+ m_pImpl.reset(new SysInfoUserAccess);
+ }
+}
+
+WinUserInfoBe::~WinUserInfoBe() {}
+
+void WinUserInfoBe::setPropertyValue(OUString const&, css::uno::Any const&)
+{
+ throw css::lang::IllegalArgumentException("setPropertyValue not supported",
+ static_cast<cppu::OWeakObject*>(this), -1);
+}
+
+css::uno::Any WinUserInfoBe::getPropertyValue(OUString const& PropertyName)
+{
+ OUString sValue;
+ // Only process the first argument of possibly multiple space- or comma-separated arguments
+ OUString sToken = PropertyName.getToken(0, ' ').getToken(0, ',');
+ if (sToken == givenname)
+ {
+ sValue = m_pImpl->GetGivenName();
+ }
+ else if (sToken == sn)
+ {
+ sValue = m_pImpl->GetSn();
+ }
+ else if (sToken == fathersname)
+ {
+ sValue = m_pImpl->GetFathersname();
+ }
+ else if (sToken == initials)
+ {
+ sValue = m_pImpl->GetInitials();
+ }
+ else if (sToken == street)
+ {
+ sValue = m_pImpl->GetStreet();
+ }
+ else if (sToken == l)
+ {
+ sValue = m_pImpl->GetCity();
+ }
+ else if (sToken == st)
+ {
+ sValue = m_pImpl->GetState();
+ }
+ else if (sToken == apartment)
+ {
+ sValue = m_pImpl->GetApartment();
+ }
+ else if (sToken == postalcode)
+ {
+ sValue = m_pImpl->GetPostalCode();
+ }
+ else if (sToken == c)
+ {
+ sValue = m_pImpl->GetCountry();
+ }
+ else if (sToken == o)
+ {
+ sValue = m_pImpl->GetOrganization();
+ }
+ else if (sToken == position)
+ {
+ sValue = m_pImpl->GetPosition();
+ }
+ else if (sToken == title)
+ {
+ sValue = m_pImpl->GetTitle();
+ }
+ else if (sToken == homephone)
+ {
+ sValue = m_pImpl->GetHomePhone();
+ }
+ else if (sToken == telephonenumber)
+ {
+ sValue = m_pImpl->GetTelephoneNumber();
+ }
+ else if (sToken == facsimiletelephonenumber)
+ {
+ sValue = m_pImpl->GetFaxNumber();
+ }
+ else if (sToken == mail)
+ {
+ sValue = m_pImpl->GetMail();
+ }
+ else
+ throw css::beans::UnknownPropertyException(sToken, static_cast<cppu::OWeakObject*>(this));
+
+ return css::uno::makeAny(css::beans::Optional<css::uno::Any>(
+ !sValue.isEmpty(), sValue.isEmpty() ? css::uno::Any() : css::uno::makeAny(sValue)));
+}
+
+OUString WinUserInfoBe::getWinUserInfoBeName()
+{
+ return OUString("com.sun.star.comp.configuration.backend.WinUserInfoBe");
+}
+
+OUString SAL_CALL WinUserInfoBe::getImplementationName() { return getWinUserInfoBeName(); }
+
+css::uno::Sequence<OUString> WinUserInfoBe::getWinUserInfoBeServiceNames()
+{
+ css::uno::Sequence<OUString> aServices{ "com.sun.star.configuration.backend.WinUserInfoBe" };
+ return aServices;
+}
+
+sal_Bool SAL_CALL WinUserInfoBe::supportsService(const OUString& aServiceName)
+{
+ return cppu::supportsService(this, aServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL WinUserInfoBe::getSupportedServiceNames()
+{
+ return getWinUserInfoBeServiceNames();
+}
+}
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/extensions/source/config/WinUserInfo/WinUserInfoBe.hxx b/extensions/source/config/WinUserInfo/WinUserInfoBe.hxx
new file mode 100644
index 000000000000..766b88c41227
--- /dev/null
+++ b/extensions/source/config/WinUserInfo/WinUserInfoBe.hxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_EXTENSIONS_SOURCE_CONFIG_WINUSERINFO_WINUSERINFOBE_HXX
+#define INCLUDED_EXTENSIONS_SOURCE_CONFIG_WINUSERINFO_WINUSERINFOBE_HXX
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/compbase.hxx>
+#include <memory>
+
+namespace com
+{
+namespace sun
+{
+namespace star
+{
+namespace uno
+{
+class XComponentContext;
+}
+}
+}
+}
+
+namespace extensions
+{
+namespace config
+{
+namespace WinUserInfo
+{
+class WinUserInfoBe_Impl;
+
+typedef cppu::WeakComponentImplHelper<css::beans::XPropertySet, css::lang::XServiceInfo>
+ BackendBase;
+
+struct WinUserInfoMutexHolder
+{
+ osl::Mutex mMutex;
+};
+/**
+ Implements the PlatformBackend service, a specialization of the
+ XPropertySet service for retrieving Active Directory user profile
+ configuration settings.
+*/
+class WinUserInfoBe : private WinUserInfoMutexHolder, public BackendBase
+{
+public:
+ explicit WinUserInfoBe(const css::uno::Reference<css::uno::XComponentContext>& xContext);
+ virtual ~WinUserInfoBe() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& aServiceName) override;
+
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override
+ {
+ return css::uno::Reference<css::beans::XPropertySetInfo>();
+ }
+
+ virtual void SAL_CALL setPropertyValue(OUString const&, css::uno::Any const&) override;
+
+ virtual css::uno::Any SAL_CALL getPropertyValue(OUString const& PropertyName) override;
+
+ virtual void SAL_CALL addPropertyChangeListener(
+ OUString const&, css::uno::Reference<css::beans::XPropertyChangeListener> const&) override
+ {
+ }
+
+ virtual void SAL_CALL removePropertyChangeListener(
+ OUString const&, css::uno::Reference<css::beans::XPropertyChangeListener> const&) override
+ {
+ }
+
+ virtual void SAL_CALL addVetoableChangeListener(
+ OUString const&, css::uno::Reference<css::beans::XVetoableChangeListener> const&) override
+ {
+ }
+
+ virtual void SAL_CALL removeVetoableChangeListener(
+ OUString const&, css::uno::Reference<css::beans::XVetoableChangeListener> const&) override
+ {
+ }
+
+ /**
+ Provides the implementation name.
+ @return implementation name
+ */
+ static OUString getWinUserInfoBeName();
+ /**
+ Provides the supported services names
+ @return service names
+ */
+ static css::uno::Sequence<OUString> getWinUserInfoBeServiceNames();
+
+private:
+ std::unique_ptr<WinUserInfoBe_Impl> m_pImpl;
+};
+}
+}
+}
+
+#endif // INCLUDED_EXTENSIONS_SOURCE_CONFIG_WINUSERINFO_WINUSERINFOBE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/extensions/source/config/WinUserInfo/componentdef.cxx b/extensions/source/config/WinUserInfo/componentdef.cxx
new file mode 100644
index 000000000000..7d8ff550445d
--- /dev/null
+++ b/extensions/source/config/WinUserInfo/componentdef.cxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "WinUserInfoBe.hxx"
+#include <cppuhelper/implementationentry.hxx>
+
+using namespace extensions::config::WinUserInfo;
+
+static css::uno::Reference<css::uno::XInterface>
+createWinUserInfoBe(const css::uno::Reference<css::uno::XComponentContext>& aContext)
+{
+ return *new WinUserInfoBe(aContext);
+}
+
+static const cppu::ImplementationEntry kImplementations_entries[]
+ = { { createWinUserInfoBe, WinUserInfoBe::getWinUserInfoBeName,
+ WinUserInfoBe::getWinUserInfoBeServiceNames, cppu::createSingleComponentFactory, nullptr,
+ 0 },
+ { nullptr, nullptr, nullptr, nullptr, nullptr, 0 } };
+
+extern "C" SAL_DLLPUBLIC_EXPORT void*
+WinUserInfoBe_component_getFactory(const sal_Char* aImplementationName, void* aServiceManager,
+ void* aRegistryKey)
+{
+ return cppu::component_getFactoryHelper(aImplementationName, aServiceManager, aRegistryKey,
+ kImplementations_entries);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/officecfg/Package_misc.mk b/officecfg/Package_misc.mk
index bfe742c11423..f873586a1770 100644
--- a/officecfg/Package_misc.mk
+++ b/officecfg/Package_misc.mk
@@ -21,5 +21,8 @@ $(eval $(call gb_Package_Package,officecfg_misc,$(SRCDIR)/officecfg))
$(eval $(call gb_Package_add_file,officecfg_misc,$(LIBO_SHARE_FOLDER)/registry/oo-ldap.xcd.sample,registry/schema/oo-ldap.xcd.sample))
$(eval $(call gb_Package_add_file,officecfg_misc,$(LIBO_SHARE_FOLDER)/registry/oo-ad-ldap.xcd.sample,registry/schema/oo-ad-ldap.xcd.sample))
+ifeq ($(OS),WNT)
+$(eval $(call gb_Package_add_file,officecfg_misc,$(LIBO_SHARE_FOLDER)/registry/oo-winuser.xcd.sample,registry/schema/oo-winuser.xcd.sample))
+endif
# vim: set noet sw=4 ts=4:
diff --git a/officecfg/registry/schema/oo-winuser.xcd.sample b/officecfg/registry/schema/oo-winuser.xcd.sample
new file mode 100644
index 000000000000..57c9b5b777c1
--- /dev/null
+++ b/officecfg/registry/schema/oo-winuser.xcd.sample
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+
+<!-- This is a fully functional configuration for WinUserInfo configuration backend.
+
+ Removing the ".sample" from the file name allows to get user data from Windows:
+ first, domain data (from Active Directory) is attempted; if unsuccessful, then
+ only given name is configured that is taken from system information.
+ In the latter case, display name (like "John Smith") would be used if present;
+ if it's not configured, then user logon name would be used.
+
+ Any properties that are not required to be set may be commented out as needed.
+-->
+
+<oor:data xmlns:oor="http://openoffice.org/2001/registry">
+ <dependency file="main"/>
+ <oor:component-data oor:package="org.openoffice" oor:name="UserProfile">
+ <node oor:name="Data">
+ <prop oor:name="o" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe o"/>
+ </prop>
+ <prop oor:name="givenname" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe givenname"/>
+ </prop>
+ <prop oor:name="sn" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe sn"/>
+ </prop>
+ <prop oor:name="initials" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe initials"/>
+ </prop>
+ <prop oor:name="street" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe street"/>
+ </prop>
+ <prop oor:name="l" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe l"/>
+ </prop>
+ <prop oor:name="st" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe st"/>
+ </prop>
+ <prop oor:name="postalcode" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe postalcode"/>
+ </prop>
+ <prop oor:name="c" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe c"/>
+ </prop>
+ <prop oor:name="title" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe title"/>
+ </prop>
+ <prop oor:name="position" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe position"/>
+ </prop>
+ <prop oor:name="homephone" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe homephone"/>
+ </prop>
+ <prop oor:name="telephonenumber" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe telephonenumber"/>
+ </prop>
+ <prop oor:name="facsimiletelephonenumber" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe facsimiletelephonenumber"/>
+ </prop>
+ <prop oor:name="mail" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe mail"/>
+ </prop>
+ <prop oor:name="fathersname" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe fathersname"/>
+ </prop>
+ <prop oor:name="apartment" oor:finalized="true">
+ <value oor:external=
+ "com.sun.star.configuration.backend.WinUserInfoBe apartment"/>
+ </prop>
+ </node>
+ </oor:component-data>
+</oor:data>
diff --git a/officecfg/registry/schema/org/openoffice/UserProfile.xcs b/officecfg/registry/schema/org/openoffice/UserProfile.xcs
index 014a6ac18c4f..478e03f82dd3 100644
--- a/officecfg/registry/schema/org/openoffice/UserProfile.xcs
+++ b/officecfg/registry/schema/org/openoffice/UserProfile.xcs
@@ -221,5 +221,16 @@
<value>true</value>
</prop>
</group>
+ <group oor:name="WinUserInfo">
+ <info>
+ <desc>Contains user information cached from Active Directory.</desc>
+ </info>
+ <prop oor:name="Cache" oor:type="xs:string" oor:nillable="false">
+ <info>
+ <desc>Cache data.</desc>
+ </info>
+ <value/>
+ </prop>
+ </group>
</component>
</oor:component-schema>
diff --git a/postprocess/Rdb_services.mk b/postprocess/Rdb_services.mk
index ff52ae00cdf5..1b1fb4cd3b92 100644
--- a/postprocess/Rdb_services.mk
+++ b/postprocess/Rdb_services.mk
@@ -300,6 +300,9 @@ $(eval $(call gb_Rdb_add_components,services,\
$(if $(ENABLE_HEADLESS),,desktop/source/splash/spl) \
extensions/source/abpilot/abp \
extensions/source/config/ldap/ldapbe2 \
+ $(if $(filter WNT,$(OS)),\
+ extensions/source/config/WinUserInfo/WinUserInfoBe \
+ ) \
extensions/source/logging/log \
extensions/source/scanner/scn \
extensions/source/update/feed/updatefeed \