Replace unowinreg.dll with execution of `reg QUERY`

The SDK's <https://wiki.openoffice.org/wiki/Documentation/DevGuide/ProUNO/Java/
Transparent_Use_of_Office_UNO_Components> on all platforms included the Windows-
specific unowinreg.dll in generated jars (so that those jars, when distributed
to a Windows environment, would find a LO installation by inspecting the Windows
registry).  That unowinreg.dll was originally built as a 32-bit DLL (though when
building a 64-bit Windows LO, it happened to be built as a 64-bit DLL).  For
non-Windows LO builds, it could either be built locally with a MinGW toolchain
(--enable-build-unowinreg) or downloaded from dev-www.libreoffice.org.

However, that had various issues:

For one, unowinreg.dll was not necessarily available in a distributed jar as a
64-bit DLL for use with a 64-bit JRE on Windows.  (Theoretically, running such a
jar with a 32-bit JRE to access a 64-bit LO installation's URE jars could have
worked.  But practically, those URE jars in turn require native DLLs, which
would then not have been available as 32-bit DLLs for use in the 32-bit JRE.)

For another, at least the unowinreg.dll resulting from --enable-build-unowinreg
on Fedora 33 would have had a dependency on libgcc_s_dw2-1.dll that would
generally not have been available in a target Windows environment.

There appears to be no pure Java way to read the Windows registry, but instead
of using a native code DLL for that, it appears to work just as well to call out
to reg.exe and parse its output.

This removes the --enable-build-unowinreg and --with-mingw-cross-compiler
configuration options.  (The sole use of the MinGW toolchain in LO was for
building unowinreg.dll.)

Change-Id: I3283ea38c884d3221a205e5ab6ec99a2691ef474
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107140
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Tested-by: Jenkins
diff --git a/Makefile.fetch b/Makefile.fetch
index 0a6202a..54c38a5 100644
--- a/Makefile.fetch
+++ b/Makefile.fetch
@@ -228,7 +228,6 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S
		$(call fetch_Optional,ZMF,ZMF_TARBALL) \
	,$(call fetch_Download_item,https://dev-www.libreoffice.org/src,$(item)))
	$(foreach item, \
		$(call fetch_Optional,ODK,UNOWINREG_DLL) \
		$(call fetch_Optional,OPENSYMBOL,OPENSYMBOL_TTF) \
		$(call fetch_Optional,ODFVALIDATOR,ODFVALIDATOR_JAR) \
		$(call fetch_Optional,OFFICEOTRON,OFFICEOTRON_JAR) \
diff --git a/Repository.mk b/Repository.mk
index c887d9b..fce601f 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -535,7 +535,6 @@ $(eval $(call gb_Helper_register_libraries,PLAINLIBS_NONE, \
	vclbootstrapprotector \
	scqahelper \
	swqahelper \
	unowinreg \
	wpftqahelper \
	precompiled_system \
	$(if $(filter MSC,$(COM)),cli_cppuhelper) \
@@ -854,7 +853,6 @@ $(eval $(call gb_Helper_register_packages_for_install,sdk,\
	$(if $(ENABLE_JAVA), \
		odk_javadoc \
		odk_uno_loader_classes \
		odk_unowinreg \
	) \
))

diff --git a/compilerplugins/clang/reservedid.cxx b/compilerplugins/clang/reservedid.cxx
index b43b1c8..2b7a69d 100644
--- a/compilerplugins/clang/reservedid.cxx
+++ b/compilerplugins/clang/reservedid.cxx
@@ -197,8 +197,6 @@ bool ReservedId::VisitNamedDecl(NamedDecl const * decl) {
                // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
            && s != "_ADOUser"
                // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
            && s != "_DllMainCRTStartup"
                // odk/source/unowinreg/win/unowinreg.cxx (TODO: needed?)
            && s != "_FcPattern" // vcl/inc/unx/fc_fontoptions.hxx
            && s != "_GdkDisplay"
                // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
diff --git a/config_host.mk.in b/config_host.mk.in
index 42f4511..add0c17 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -53,7 +53,6 @@ export BSH_JAR=@BSH_JAR@
export BUILD_PLATFORM=@build@
export BUILD_POSTGRESQL_SDBC=@BUILD_POSTGRESQL_SDBC@
export BUILD_TYPE=@BUILD_TYPE@
export BUILD_UNOWINREG=@BUILD_UNOWINREG@
export BUILD_X64=@BUILD_X64@
export BUILD_X86=@BUILD_X86@
export BUILDING_PCH_WITH_OBJ=@BUILDING_PCH_WITH_OBJ@
@@ -423,8 +422,6 @@ export BUNDLE_MARIADB_CONNECTOR_C=@BUNDLE_MARIADB_CONNECTOR_C@
export MDDS_CFLAGS=$(gb_SPACE)@MDDS_CFLAGS@
export MDDS_LIBS=$(gb_SPACE)@MDDS_LIBS@
export MERGELIBS=@MERGELIBS@
export MINGWCXX=@MINGWCXX@
export MINGWSTRIP=@MINGWSTRIP@
export ML_EXE=@ML_EXE@
export MOC5=@MOC5@
export MPL_SUBSET=@MPL_SUBSET@
@@ -637,7 +634,6 @@ export TOUCH=@TOUCH@
export UCRTSDKDIR=@UCRTSDKDIR@
export UCRTVERSION=@UCRTVERSION@
export UCRT_REDISTDIR=@UCRT_REDISTDIR@
export UNOWINREG_DLL=@UNOWINREG_DLL@
export USE_LD=@USE_LD@
export USE_LIBRARY_BIN_TAR=@USE_LIBRARY_BIN_TAR@
export USE_XINERAMA=@USE_XINERAMA@
diff --git a/configure.ac b/configure.ac
index 3827f49..3f418e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1644,12 +1644,6 @@ libo_FUZZ_ARG_ENABLE(chart-tests,
         who can judge if a test failure is a regression or not.]),
,)

AC_ARG_ENABLE(build-unowinreg,
    AS_HELP_STRING([--enable-build-unowinreg],
        [Do not use the prebuilt unowinreg.dll. Build it instead. The MinGW C++
         compiler is needed on Linux.]),
,)

AC_ARG_ENABLE(build-opensymbol,
    AS_HELP_STRING([--enable-build-opensymbol],
        [Do not use the prebuilt opens___.ttf. Build it instead. This needs
@@ -2549,13 +2543,6 @@ AC_ARG_WITH(os-version,
        [For FreeBSD users, use this option to override the detected OSVERSION.]),
,)

AC_ARG_WITH(mingw-cross-compiler,
    AS_HELP_STRING([--with-mingw-cross-compiler=<mingw32-g++ command>],
        [Specify the MinGW cross-compiler to use.
         When building on the ODK on Unix and building unowinreg.dll,
         specify the MinGW C++ cross-compiler.]),
,)

AC_ARG_WITH(idlc-cpp,
    AS_HELP_STRING([--with-idlc-cpp=<cpp/ucpp>],
        [Specify the C Preprocessor to use for idlc. Default is ucpp.]),
@@ -4072,12 +4059,6 @@ AC_SUBST(VCVER)
AC_SUBST(DEVENV)
AC_SUBST(MSVC_CXX)

#
# unowinreg.dll
#
UNOWINREG_DLL="185d60944ea767075d27247c3162b3bc-unowinreg.dll"
AC_SUBST(UNOWINREG_DLL)

COM_IS_CLANG=
AC_MSG_CHECKING([whether the compiler is actually Clang])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
@@ -8717,54 +8698,10 @@ AC_SUBST([DOXYGEN])
AC_MSG_CHECKING([whether to build the ODK])
if test "$enable_odk" = "" -o "$enable_odk" != "no"; then
    AC_MSG_RESULT([yes])

    if test "$with_java" != "no"; then
        AC_MSG_CHECKING([whether to build unowinreg.dll])
        if test "$_os" = "WINNT" -a "$enable_build_unowinreg" = ""; then
            # build on Win by default
            enable_build_unowinreg=yes
        fi
        if test "$enable_build_unowinreg" = "" -o "$enable_build_unowinreg" = "no"; then
            AC_MSG_RESULT([no])
            BUILD_UNOWINREG=
        else
            AC_MSG_RESULT([yes])
            BUILD_UNOWINREG=TRUE
        fi
        if test "$_os" != "WINNT" -a "$BUILD_UNOWINREG" = "TRUE"; then
            if test -z "$with_mingw_cross_compiler"; then
                dnl Guess...
                AC_CHECK_PROGS(MINGWCXX,i386-mingw32msvc-g++ i586-pc-mingw32-g++ i686-pc-mingw32-g++ i686-w64-mingw32-g++,false)
            elif test -x "$with_mingw_cross_compiler"; then
                 MINGWCXX="$with_mingw_cross_compiler"
            else
                AC_CHECK_TOOL(MINGWCXX, "$with_mingw_cross_compiler", false)
            fi

            if test "$MINGWCXX" = "false"; then
                AC_MSG_ERROR([MinGW32 C++ cross-compiler not found.])
            fi

            mingwstrip_test="`echo $MINGWCXX | $SED -e s/g++/strip/`"
            if test -x "$mingwstrip_test"; then
                MINGWSTRIP="$mingwstrip_test"
            else
                AC_CHECK_TOOL(MINGWSTRIP, "$mingwstrip_test", false)
            fi

            if test "$MINGWSTRIP" = "false"; then
                AC_MSG_ERROR(MinGW32 binutils not found.)
            fi
        fi
    fi
    BUILD_TYPE="$BUILD_TYPE ODK"
else
    AC_MSG_RESULT([no])
    BUILD_UNOWINREG=
fi
AC_SUBST(BUILD_UNOWINREG)
AC_SUBST(MINGWCXX)
AC_SUBST(MINGWSTRIP)

dnl ===================================================================
dnl Check for system zlib
diff --git a/download.lst b/download.lst
index bff5f06..5f1be45 100644
--- a/download.lst
+++ b/download.lst
@@ -271,5 +271,4 @@ export ZMF_SHA256SUM := 27051a30cb057fdb5d5de65a1f165c7153dc76e27fe62251cbb86639
export ZMF_TARBALL := libzmf-0.0.2.tar.xz

NUMBERTEXT_EXTENSION_SHA256SUM := 1568ed1d2feb8210bb5de61d69574a165cded536cfa17c6953c9064076469de2
UNOWINREG_SHA256SUM := eafde646a7dbe46d20c291685b0beac2382174d78d66ee990e229a1bf6e6cec6
OPENSYMBOL_SHA256SUM := f543e6e2d7275557a839a164941c0a86e5f2c3f2a0042bfc434c88c6dde9e140
diff --git a/odk/CustomTarget_check.mk b/odk/CustomTarget_check.mk
index 69b99a9..7433195 100644
--- a/odk/CustomTarget_check.mk
+++ b/odk/CustomTarget_check.mk
@@ -38,8 +38,7 @@ $(call gb_CustomTarget_get_workdir,odk/check)/checkbin : \
		$(call gb_Package_get_target,odk_html) \
		$(if $(ENABLE_JAVA),$(call gb_GeneratedPackage_get_target,odk_javadoc)) \
		$(call gb_Package_get_target,odk_settings) \
		$(call gb_Package_get_target,odk_settings_generated) \
		$(if $(ENABLE_JAVA),$(call gb_Package_get_target,odk_unowinreg))
		$(call gb_Package_get_target,odk_settings_generated)
ifneq ($(gb_SUPPRESS_TESTS),)
	@true
else
diff --git a/odk/CustomTarget_unowinreg.mk b/odk/CustomTarget_unowinreg.mk
deleted file mode 100644
index 3a46ddf..0000000
--- a/odk/CustomTarget_unowinreg.mk
+++ /dev/null
@@ -1,26 +0,0 @@
# -*- 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_CustomTarget_CustomTarget,odk/unowinreg))

$(eval $(call gb_CustomTarget_register_target,odk/unowinreg,unowinreg.dll))

$(call gb_CustomTarget_get_workdir,odk/unowinreg)/unowinreg.dll : \
		$(SRCDIR)/odk/source/unowinreg/win/unowinreg.cxx
	$(MINGWCXX) -Wall -D_JNI_IMPLEMENTATION_ \
		-I$(JAVA_HOME)/include \
		$(if $(filter LINUX,$(OS)),-I$(JAVA_HOME)/include/linux,\
		$(if $(filter FREEBSD,$(OS)),-I$(JAVA_HOME)/include/freebsd \
		-I$(JAVA_HOME)/include/bsd -I$(JAVA_HOME)/include/linux,\
		$(if $(filter NETBSD,$(OS)),-I$(JAVA_HOME)/include/netbsd))) \
		-shared -o $@ $< \
		-Wl,--kill-at -lkernel32 -ladvapi32 && \
	$(MINGWSTRIP) $@

# vim: set noet sw=4 ts=4:
diff --git a/odk/Library_unowinreg.mk b/odk/Library_unowinreg.mk
deleted file mode 100644
index a514168..0000000
--- a/odk/Library_unowinreg.mk
+++ /dev/null
@@ -1,36 +0,0 @@
# -*- 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,unowinreg))

ifeq ($(COM),GCC)
$(eval $(call gb_Library_add_libs,unowinreg,\
	-lstdc++ \
	-lgcc_eh \
	-lgcc \
	-lmingw32 \
	-lmoldname \
	-lmsvcrt \
))
else
$(eval $(call gb_Library_add_ldflags,unowinreg,\
	/MANIFEST:NO \
))
endif

$(eval $(call gb_Library_add_exception_objects,unowinreg,\
   odk/source/unowinreg/win/unowinreg \
))

$(eval $(call gb_Library_use_system_win32_libs,unowinreg,\
	kernel32 \
	advapi32 \
))

# vim: set noet sw=4 ts=4:
diff --git a/odk/Module_odk.mk b/odk/Module_odk.mk
index 120d8a4..6938853 100644
--- a/odk/Module_odk.mk
+++ b/odk/Module_odk.mk
@@ -41,13 +41,10 @@ endif

ifneq ($(ENABLE_JAVA),)
$(eval $(call gb_Module_add_targets,odk,\
	$(if $(and $(BUILD_UNOWINREG),$(filter GCC,$(COM))),CustomTarget_unowinreg)\
	CustomTarget_classes \
	CustomTarget_javadoc \
	GeneratedPackage_odk_javadoc \
	GeneratedPackage_uno_loader_classes \
	$(if $(filter WNT,$(OS)),Library_unowinreg) \
	Package_unowinreg \
))
endif

diff --git a/odk/Package_unowinreg.mk b/odk/Package_unowinreg.mk
deleted file mode 100644
index 189967e..0000000
--- a/odk/Package_unowinreg.mk
+++ /dev/null
@@ -1,28 +0,0 @@
# -*- 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/.
#

ifneq ($(BUILD_UNOWINREG),)
ifeq ($(COM),MSC)
odk_unowinreg_DIR := $(WORKDIR)/LinkTarget/Library
else
odk_unowinreg_DIR := $(call gb_CustomTarget_get_workdir,odk/unowinreg)
endif
odk_unowinreg_FILE := unowinreg.dll
else # !BUILD_UNOWINREG
odk_unowinreg_DIR := $(TARFILE_LOCATION)
odk_unowinreg_FILE := $(UNOWINREG_DLL)
endif

$(eval $(call gb_Package_Package,odk_unowinreg,$(odk_unowinreg_DIR)))

$(eval $(call gb_Package_set_outdir,odk_unowinreg,$(INSTDIR)))

$(eval $(call gb_Package_add_file,odk_unowinreg,$(SDKDIRNAME)/classes/win/unowinreg.dll,$(odk_unowinreg_FILE)))

# vim: set noet sw=4 ts=4:
diff --git a/odk/examples/DevelopersGuide/FirstSteps/build_FirstUnoContact.xml b/odk/examples/DevelopersGuide/FirstSteps/build_FirstUnoContact.xml
index 4dec9aa..ec0eba7 100644
--- a/odk/examples/DevelopersGuide/FirstSteps/build_FirstUnoContact.xml
+++ b/odk/examples/DevelopersGuide/FirstSteps/build_FirstUnoContact.xml
@@ -34,7 +34,6 @@
    <fileset id="bootstrap.glue.code" dir="${OO_SDK_HOME}/classes">
        <patternset>
            <include name="com/sun/star/lib/loader/*.class"/>
            <include name="win/unowinreg.dll"/>
        </patternset>
    </fileset>

diff --git a/odk/settings/std.mk b/odk/settings/std.mk
index dfa01e66..0923a27 100644
--- a/odk/settings/std.mk
+++ b/odk/settings/std.mk
@@ -94,5 +94,4 @@ JAVAMAKER="$(OO_SDK_HOME)/bin/javamaker"
REGMERGE="$(OO_SDK_URE_BIN_DIR)/regmerge"

SDK_JAVA_UNO_BOOTSTRAP_FILES=\
    -C $(CLASSES_DIR) $(SQM)com/sun/star/lib/loader/$(SQM) \
    -C $(CLASSES_DIR) $(SQM)win/unowinreg.dll$(SQM)
    -C $(CLASSES_DIR) $(SQM)com/sun/star/lib/loader/$(SQM)
diff --git a/odk/source/com/sun/star/lib/loader/InstallationFinder.java b/odk/source/com/sun/star/lib/loader/InstallationFinder.java
index 77c0424..8178e06 100644
--- a/odk/source/com/sun/star/lib/loader/InstallationFinder.java
+++ b/odk/source/com/sun/star/lib/loader/InstallationFinder.java
@@ -189,20 +189,20 @@ final class InstallationFinder {
     */
    private static String getPathFromWindowsRegistry() {

        final String SUBKEYNAME = "Software\\LibreOffice\\UNO\\InstallPath";
        final String SUBKEYNAME = "\\Software\\LibreOffice\\UNO\\InstallPath";

        String path = null;

        try {
            // read the key's default value from HKEY_CURRENT_USER
            WinRegKey key = new WinRegKey( "HKEY_CURRENT_USER", SUBKEYNAME );
            path = key.getStringValue( "" ); // default
            WinRegKey key = new WinRegKey( "HKEY_CURRENT_USER" + SUBKEYNAME );
            path = key.getStringValue();
        } catch ( WinRegKeyException e ) {
            try {
                // read the key's default value from HKEY_LOCAL_MACHINE
                WinRegKey key = new WinRegKey( "HKEY_LOCAL_MACHINE",
                WinRegKey key = new WinRegKey( "HKEY_LOCAL_MACHINE" +
                                               SUBKEYNAME );
                path = key.getStringValue( "" ); // default
                path = key.getStringValue();
            } catch ( WinRegKeyException we ) {
                System.err.println( "com.sun.star.lib.loader." +
                    "InstallationFinder::getPathFromWindowsRegistry: " +
diff --git a/odk/source/com/sun/star/lib/loader/WinRegKey.java b/odk/source/com/sun/star/lib/loader/WinRegKey.java
index 12cfc45..bdbcced 100644
--- a/odk/source/com/sun/star/lib/loader/WinRegKey.java
+++ b/odk/source/com/sun/star/lib/loader/WinRegKey.java
@@ -19,185 +19,62 @@

package com.sun.star.lib.loader;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class provides functionality for reading string values from the
 * Windows Registry. It requires the native library unowinreg.dll.
 * Windows Registry.
 */
final class WinRegKey {

    private final String m_rootKeyName;
    private final String m_subKeyName;

    // native methods to access the windows registry
    private static native boolean winreg_RegOpenClassesRoot( long[] hkresult );
    private static native boolean winreg_RegOpenCurrentConfig(
        long[] hkresult );
    private static native boolean winreg_RegOpenCurrentUser( long[] hkresult );
    private static native boolean winreg_RegOpenLocalMachine( long[] hkresult );
    private static native boolean winreg_RegOpenUsers( long[] hkresult );
    private static native boolean winreg_RegOpenKeyEx( long parent, String name,
        long[] hkresult );
    private static native boolean winreg_RegCloseKey( long hkey );
    private static native boolean winreg_RegQueryValueEx(
        long hkey, String value, long[] type,
        byte[] data, long[] size );
    private static native boolean winreg_RegQueryInfoKey(
        long hkey, long[] subkeys, long[] maxSubkeyLen,
        long[] values, long[] maxValueNameLen,
        long[] maxValueLen, long[] secDescriptor );

    // load the native library unowinreg.dll
    static {
        try {
            ClassLoader cl = WinRegKey.class.getClassLoader();
            InputStream is = cl.getResourceAsStream( "win/unowinreg.dll" );
            if ( is != null ) {
                // generate a temporary name for lib file and write to temp
                // location
                File libfile;
                BufferedInputStream istream = null;
                BufferedOutputStream ostream = null;
                try {
                    istream = new BufferedInputStream( is );
                    libfile = File.createTempFile( "unowinreg", ".dll" );
                    libfile.deleteOnExit(); // ensure deletion
                    ostream = new BufferedOutputStream(
                        new FileOutputStream( libfile ) );
                    int bsize = 2048; int n = 0;
                    byte[] buffer = new byte[bsize];
                    while ( ( n = istream.read( buffer, 0, bsize ) ) != -1 ) {
                        ostream.write( buffer, 0, n );
                    }
                } finally {
                    if (istream != null) {
                        istream.close();
                    }
                    if (ostream != null) {
                        ostream.close();
                    }
                }
                // load library
                System.load( libfile.getPath() );
            } else {
                // If the library cannot be found as a class loader resource,
                // try the global System.loadLibrary(). The JVM will look for
                // it in the java.library.path.
                System.loadLibrary( "unowinreg" );
            }
        } catch ( java.lang.Exception e ) {
            System.err.println( "com.sun.star.lib.loader.WinRegKey: " +
                "loading of native library failed!" + e );
        }
    }
    private final String m_keyName;

    /**
     * Constructs a <code>WinRegKey</code>.
     */
    public WinRegKey( String rootKeyName, String subKeyName ) {
        m_rootKeyName = rootKeyName;
        m_subKeyName = subKeyName;
    public WinRegKey( String keyName ) {
        m_keyName = keyName;
    }

    /**
     * Reads a string value for the specified value name.
     * Reads the default string value.
     */
    public String getStringValue( String valueName ) throws WinRegKeyException {
        byte[] data = getValue( valueName );
        // remove terminating null character
        return new String( data, 0, data.length - 1 );
    }

    /**
     * Reads a value for the specified value name.
     */
    private byte[] getValue( String valueName ) throws WinRegKeyException {

        byte[] result = null;
        long[] hkey = {0};

        // open the specified registry key
        boolean bRet = false;
        long[] hroot = {0};
        if ( m_rootKeyName.equals( "HKEY_CLASSES_ROOT" ) ) {
            bRet = winreg_RegOpenClassesRoot( hroot );
        } else if ( m_rootKeyName.equals( "HKEY_CURRENT_CONFIG" ) ) {
            bRet = winreg_RegOpenCurrentConfig( hroot );
        } else if ( m_rootKeyName.equals( "HKEY_CURRENT_USER" ) ) {
            bRet = winreg_RegOpenCurrentUser( hroot );
        } else if ( m_rootKeyName.equals( "HKEY_LOCAL_MACHINE" ) ) {
            bRet = winreg_RegOpenLocalMachine( hroot );
        } else if ( m_rootKeyName.equals( "HKEY_USERS" ) ) {
            bRet = winreg_RegOpenUsers( hroot );
        } else {
            throw new WinRegKeyException( "unknown root registry key!");
        }
        if ( !bRet ) {
            throw new WinRegKeyException( "opening root registry key " +
                "failed!" );
        }
        if ( !winreg_RegOpenKeyEx( hroot[0], m_subKeyName, hkey ) ) {
            if ( !winreg_RegCloseKey( hroot[0] ) ) {
                throw new WinRegKeyException( "opening registry key and " +
                    "releasing root registry key handle failed!" );
    public String getStringValue() throws WinRegKeyException {
        try {
            Process p = Runtime.getRuntime().exec(new String[]{"reg", "QUERY", m_keyName});
            BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String v = null;
            Pattern pt = Pattern.compile("\\s+\\(Default\\)\\s+REG_SZ\\s+(.+)");
            for (;;) {
                String s = r.readLine();
                if (s == null) {
                    break;
                }
                Matcher m = pt.matcher(s);
                if (m.matches()) {
                    if (v != null) {
                        throw new WinRegKeyException("reg QUERY did not provided expected output");
                    }
                    v = m.group(1);
                }
            }
            throw new WinRegKeyException( "opening registry key failed!" );
        }

        // get the size of the longest data component among the key's values
        long[] subkeys = {0};
        long[] maxSubkeyLen = {0};
        long[] values = {0};
        long[] maxValueNameLen = {0};
        long[] maxValueLen = {0};
        long[] secDescriptor = {0};
        if ( !winreg_RegQueryInfoKey( hkey[0], subkeys, maxSubkeyLen,
                 values, maxValueNameLen, maxValueLen, secDescriptor ) ) {
            if ( !winreg_RegCloseKey( hkey[0] ) ||
                 !winreg_RegCloseKey( hroot[0] ) ) {
                throw new WinRegKeyException( "retrieving information about " +
                    "the registry key and releasing registry key handles " +
                    "failed!" );
            p.waitFor();
            int e = p.exitValue();
            if (e != 0) {
                throw new WinRegKeyException("reg QUERY exited with " + e);
            }
            throw new WinRegKeyException( "retrieving information about " +
                "the registry key failed!" );
        }

        // get the data for the specified value name
        byte[] buffer = new byte[ (int) maxValueLen[0] ];
        long[] size = new long[1];
        size[0] = buffer.length;
        long[] type = new long[1];
        type[0] = 0;
        if ( !winreg_RegQueryValueEx( hkey[0], valueName, type, buffer,
                 size ) ) {
            if ( !winreg_RegCloseKey( hkey[0] ) ||
                 !winreg_RegCloseKey( hroot[0] ) ) {
                throw new WinRegKeyException( "retrieving data for the " +
                    "specified value name and releasing registry key handles " +
                    "failed!" );
            if (v == null) {
                throw new WinRegKeyException("reg QUERY did not provided expected output");
            }
            throw new WinRegKeyException( "retrieving data for the " +
                "specified value name failed!" );
            return v;
        } catch (WinRegKeyException e) {
            throw e;
        } catch (Exception e) {
            throw new WinRegKeyException(e);
        }

        // release registry key handles
        if ( !winreg_RegCloseKey( hkey[0] ) ||
             !winreg_RegCloseKey( hroot[0] ) ) {
            throw new WinRegKeyException( "releasing registry key handles " +
                "failed!" );
        }

        result = new byte[ (int) size[0] ];
        System.arraycopy( buffer, 0, result, 0, (int)size[0] );

        return result;
    }
}

diff --git a/odk/source/com/sun/star/lib/loader/WinRegKeyException.java b/odk/source/com/sun/star/lib/loader/WinRegKeyException.java
index aee93c0..56abc75 100644
--- a/odk/source/com/sun/star/lib/loader/WinRegKeyException.java
+++ b/odk/source/com/sun/star/lib/loader/WinRegKeyException.java
@@ -27,8 +27,8 @@ final class WinRegKeyException extends java.lang.Exception {
    /**
     * Constructs a <code>WinRegKeyException</code>.
     */
    public WinRegKeyException() {
        super();
    public WinRegKeyException(Throwable cause) {
        super(cause);
    }

    /**
diff --git a/odk/source/unowinreg/win/unowinreg.cxx b/odk/source/unowinreg/win/unowinreg.cxx
deleted file mode 100644
index ba28809..0000000
--- a/odk/source/unowinreg/win/unowinreg.cxx
+++ /dev/null
@@ -1,170 +0,0 @@
/* -*- 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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#if !defined WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>

#include <jni.h>

extern "C" BOOL __stdcall _DllMainCRTStartup(HINSTANCE, DWORD, LPVOID)
{
    return TRUE;
}

extern "C" JNIEXPORT jboolean JNICALL
    Java_com_sun_star_lib_loader_WinRegKey_winreg_1RegOpenClassesRoot(
    JNIEnv *env, jclass, jlongArray hkresult)
{
    bool ret = JNI_FALSE;
    auto phkey = env->GetLongArrayElements(hkresult, nullptr);
    if (RegOpenKeyEx(HKEY_CLASSES_ROOT, nullptr, 0, KEY_READ, reinterpret_cast<PHKEY>(phkey))
        == ERROR_SUCCESS)
        ret = JNI_TRUE;
    env->ReleaseLongArrayElements(hkresult, phkey, 0);
    return ret;
}

extern "C" JNIEXPORT jboolean JNICALL
    Java_com_sun_star_lib_loader_WinRegKey_winreg_1RegOpenCurrentConfig(
    JNIEnv *env, jclass, jlongArray hkresult)
{
    bool ret = JNI_FALSE;
    auto phkey = env->GetLongArrayElements(hkresult, nullptr);
    if (RegOpenKeyEx(HKEY_CURRENT_CONFIG, nullptr, 0, KEY_READ, reinterpret_cast<PHKEY>(phkey))
        == ERROR_SUCCESS)
        ret = JNI_TRUE;
    env->ReleaseLongArrayElements(hkresult, phkey, 0);
    return ret;
}

extern "C" JNIEXPORT jboolean JNICALL
    Java_com_sun_star_lib_loader_WinRegKey_winreg_1RegOpenCurrentUser(
    JNIEnv *env, jclass, jlongArray hkresult)
{
    bool ret = JNI_FALSE;
    auto phkey = env->GetLongArrayElements(hkresult, nullptr);
    if (RegOpenKeyEx(HKEY_CURRENT_USER, nullptr, 0, KEY_READ, reinterpret_cast<PHKEY>(phkey))
        == ERROR_SUCCESS)
        ret = JNI_TRUE;
    env->ReleaseLongArrayElements(hkresult, phkey, 0);
    return ret;
}

extern "C" JNIEXPORT jboolean JNICALL
    Java_com_sun_star_lib_loader_WinRegKey_winreg_1RegOpenLocalMachine(
    JNIEnv *env, jclass, jlongArray hkresult)
{
    bool ret = JNI_FALSE;
    auto phkey = env->GetLongArrayElements(hkresult, nullptr);
    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, nullptr, 0, KEY_READ, reinterpret_cast<PHKEY>(phkey))
        == ERROR_SUCCESS)
        ret = JNI_TRUE;
    env->ReleaseLongArrayElements(hkresult, phkey, 0);
    return ret;
}

extern "C" JNIEXPORT jboolean JNICALL
    Java_com_sun_star_lib_loader_WinRegKey_winreg_1RegOpenUsers(
    JNIEnv *env, jclass, jlongArray hkresult)
{
    bool ret = JNI_FALSE;
    auto phkey = env->GetLongArrayElements(hkresult, nullptr);
    if (RegOpenKeyEx(HKEY_USERS, nullptr, 0, KEY_READ, reinterpret_cast<PHKEY>(phkey)) == ERROR_SUCCESS)
        ret = JNI_TRUE;
    env->ReleaseLongArrayElements(hkresult, phkey, 0);
    return ret;
}

extern "C" JNIEXPORT jboolean JNICALL
    Java_com_sun_star_lib_loader_WinRegKey_winreg_1RegOpenKeyEx(
    JNIEnv *env, jclass, jlong parent, jstring name, jlongArray hkresult)
{
    bool ret = JNI_FALSE;
    const char *namestr = env->GetStringUTFChars(name, nullptr);
    auto phkey = env->GetLongArrayElements(hkresult, nullptr);
    if (RegOpenKeyEx(reinterpret_cast<HKEY>(parent), namestr, 0, KEY_READ, reinterpret_cast<PHKEY>(phkey))
        == ERROR_SUCCESS)
        ret = JNI_TRUE;
    env->ReleaseStringUTFChars(name, namestr);
    env->ReleaseLongArrayElements(hkresult, phkey, 0);
    return ret;
}


extern "C" JNIEXPORT jboolean JNICALL
    Java_com_sun_star_lib_loader_WinRegKey_winreg_1RegCloseKey(
    JNIEnv *, jclass, jlong hkey)
{
    bool ret = JNI_FALSE;
    if (RegCloseKey(reinterpret_cast<HKEY>(hkey)) == ERROR_SUCCESS)
        ret = JNI_TRUE;
    return ret;
}

extern "C" JNIEXPORT jboolean
    JNICALL Java_com_sun_star_lib_loader_WinRegKey_winreg_1RegQueryValueEx(
    JNIEnv *env, jclass, jlong hkey, jstring value, jlongArray type,
    jbyteArray data, jlongArray size)
{
    bool ret = JNI_FALSE;
    const char* valuestr = env->GetStringUTFChars(value, nullptr);
    auto ptype = env->GetLongArrayElements(type, nullptr);
    auto pdata = env->GetByteArrayElements(data, nullptr);
    auto psize = env->GetLongArrayElements(size, nullptr);
    if (RegQueryValueEx(reinterpret_cast<HKEY>(hkey), valuestr, nullptr, reinterpret_cast<LPDWORD>(ptype), reinterpret_cast<LPBYTE>(pdata), reinterpret_cast<LPDWORD>(psize))
        == ERROR_SUCCESS)
        ret = JNI_TRUE;
    env->ReleaseStringUTFChars(value, valuestr);
    env->ReleaseLongArrayElements(type, ptype, 0);
    env->ReleaseByteArrayElements(data, pdata, 0);
    env->ReleaseLongArrayElements(size, psize, 0);
    return ret;
}

extern "C" JNIEXPORT jboolean JNICALL
    Java_com_sun_star_lib_loader_WinRegKey_winreg_1RegQueryInfoKey(
    JNIEnv *env, jclass, jlong hkey, jlongArray subkeys,
    jlongArray maxSubkeyLen, jlongArray values, jlongArray maxValueNameLen,
    jlongArray maxValueLen, jlongArray secDescriptor)
{
    bool ret = JNI_FALSE;
    auto psubkeys = env->GetLongArrayElements(subkeys, nullptr);
    auto pmaxSubkeyLen = env->GetLongArrayElements(maxSubkeyLen, nullptr);
    auto pvalues = env->GetLongArrayElements(values, nullptr);
    auto pmaxValueNameLen = env->GetLongArrayElements(maxValueNameLen, nullptr);
    auto pmaxValueLen = env->GetLongArrayElements(maxValueLen, nullptr);
    auto psecDescriptor = env->GetLongArrayElements(secDescriptor, nullptr);
    FILETIME ft;
    if (RegQueryInfoKey(reinterpret_cast<HKEY>(hkey), nullptr, nullptr, nullptr, reinterpret_cast<LPDWORD>(psubkeys), reinterpret_cast<LPDWORD>(pmaxSubkeyLen),
                        nullptr, reinterpret_cast<LPDWORD>(pvalues), reinterpret_cast<LPDWORD>(pmaxValueNameLen), reinterpret_cast<LPDWORD>(pmaxValueLen),
                        reinterpret_cast<LPDWORD>(psecDescriptor), &ft) == ERROR_SUCCESS)
        ret = JNI_TRUE;
    env->ReleaseLongArrayElements(subkeys, psubkeys, 0);
    env->ReleaseLongArrayElements(maxSubkeyLen, pmaxSubkeyLen, 0);
    env->ReleaseLongArrayElements(values, pvalues, 0);
    env->ReleaseLongArrayElements(maxValueNameLen, pmaxValueNameLen, 0);
    env->ReleaseLongArrayElements(maxValueLen, pmaxValueLen, 0);
    env->ReleaseLongArrayElements(secDescriptor, psecDescriptor, 0);
    return ret;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist
index 5249848..fddf4b2 100644
--- a/solenv/clang-format/excludelist
+++ b/solenv/clang-format/excludelist
@@ -7105,7 +7105,6 @@ odk/examples/cpp/custompanel/ctp_services.cxx
odk/examples/cpp/remoteclient/remoteclient.cxx
odk/source/unoapploader/unx/unoapploader.c
odk/source/unoapploader/win/unoapploader.c
odk/source/unowinreg/win/unowinreg.cxx
officecfg/qa/cppheader.cxx
onlineupdate/inc/Char16.h
onlineupdate/source/libmar/sign/mar_sign.c