diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h
index f2d7412321ca9a543df171d47e4bf534463733ba..a4664ed85a9b3e544b3037fe4360a1b29a60aa41 100644
--- a/dlls/crypt32/crypt32_private.h
+++ b/dlls/crypt32/crypt32_private.h
@@ -460,8 +460,10 @@ void init_empty_store(void) DECLSPEC_HIDDEN;
 #define IS_INTOID(x)    (((ULONG_PTR)(x) >> 16) == 0)
 
 /* Unix interface */
+
 struct unix_funcs
 {
+    BOOL (WINAPI *enum_root_certs)( void *buffer, SIZE_T size, SIZE_T *needed );
     BOOL (WINAPI *import_cert_store)( CRYPT_DATA_BLOB *pfx, const WCHAR *password, DWORD flags,
                                       void **key_ret, void ***chain_ret, DWORD *count_ret );
 };
diff --git a/dlls/crypt32/pfx.c b/dlls/crypt32/pfx.c
index d0e0cb9d2d6cbb7368000a8a4a096ec9e8c2516f..a7ac41ca6775bd52550557b6ca12b67901cb9798 100644
--- a/dlls/crypt32/pfx.c
+++ b/dlls/crypt32/pfx.c
@@ -151,7 +151,7 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
         FIXME( "flags %08x not supported\n", flags );
         return NULL;
     }
-    if (!unix_funcs)
+    if (!unix_funcs->import_cert_store)
     {
         FIXME( "(%p, %p, %08x)\n", pfx, password, flags );
         return NULL;
diff --git a/dlls/crypt32/rootstore.c b/dlls/crypt32/rootstore.c
index f795181bcf62411c7e030226a75f13d304fcda80..5e5782d3ef84aa7fd81fc12844baf3d483db9fa7 100644
--- a/dlls/crypt32/rootstore.c
+++ b/dlls/crypt32/rootstore.c
@@ -46,114 +46,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 
-#define INITIAL_CERT_BUFFER 1024
-
-struct DynamicBuffer
-{
-    DWORD allocated;
-    DWORD used;
-    BYTE *data;
-};
-
-static inline void reset_buffer(struct DynamicBuffer *buffer)
-{
-    buffer->used = 0;
-    if (buffer->data) buffer->data[0] = 0;
-}
-
-static BOOL add_line_to_buffer(struct DynamicBuffer *buffer, LPCSTR line)
-{
-    BOOL ret;
-
-    if (buffer->used + strlen(line) + 1 > buffer->allocated)
-    {
-        if (!buffer->allocated)
-        {
-            buffer->data = CryptMemAlloc(INITIAL_CERT_BUFFER);
-            if (buffer->data)
-            {
-                buffer->data[0] = 0;
-                buffer->allocated = INITIAL_CERT_BUFFER;
-            }
-        }
-        else
-        {
-            DWORD new_size = max(buffer->allocated * 2,
-             buffer->used + strlen(line) + 1);
-
-            buffer->data = CryptMemRealloc(buffer->data, new_size);
-            if (buffer->data)
-                buffer->allocated = new_size;
-        }
-    }
-    if (buffer->data)
-    {
-        strcpy((char *)buffer->data + strlen((char *)buffer->data), line);
-        /* Not strlen + 1, otherwise we'd count the NULL for every line's
-         * addition (but we overwrite the previous NULL character.)  Not an
-         * overrun, we allocate strlen + 1 bytes above.
-         */
-        buffer->used += strlen(line);
-        ret = TRUE;
-    }
-    else
-        ret = FALSE;
-    return ret;
-}
-
-/* Reads any base64-encoded certificates present in fp and adds them to store.
- * Returns TRUE if any certificates were successfully imported.
- */
-static BOOL import_base64_certs_from_fp(FILE *fp, HCERTSTORE store)
-{
-    char line[1024];
-    BOOL in_cert = FALSE;
-    struct DynamicBuffer saved_cert = { 0, 0, NULL };
-    int num_certs = 0;
-
-    TRACE("\n");
-    while (fgets(line, sizeof(line), fp))
-    {
-        static const char header[] = "-----BEGIN CERTIFICATE-----";
-        static const char trailer[] = "-----END CERTIFICATE-----";
-
-        if (!strncmp(line, header, strlen(header)))
-        {
-            TRACE("begin new certificate\n");
-            in_cert = TRUE;
-            reset_buffer(&saved_cert);
-        }
-        else if (!strncmp(line, trailer, strlen(trailer)))
-        {
-            DWORD size;
-
-            TRACE("end of certificate, adding cert\n");
-            in_cert = FALSE;
-            if (CryptStringToBinaryA((char *)saved_cert.data, saved_cert.used,
-             CRYPT_STRING_BASE64, NULL, &size, NULL, NULL))
-            {
-                LPBYTE buf = CryptMemAlloc(size);
-
-                if (buf)
-                {
-                    CryptStringToBinaryA((char *)saved_cert.data,
-                     saved_cert.used, CRYPT_STRING_BASE64, buf, &size, NULL,
-                     NULL);
-                    if (CertAddEncodedCertificateToStore(store,
-                     X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_NEW, NULL))
-                        num_certs++;
-                    CryptMemFree(buf);
-                }
-            }
-        }
-        else if (in_cert)
-            add_line_to_buffer(&saved_cert, line);
-    }
-    CryptMemFree(saved_cert.data);
-    TRACE("Read %d certs\n", num_certs);
-    return num_certs > 0;
-}
-
 static const char *trust_status_to_str(DWORD status)
 {
     static const struct
@@ -291,146 +183,6 @@ static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to)
     TRACE("Added %d root certificates\n", root_count);
 }
 
-/* Reads the file fd, and imports any certificates in it into store.
- * Returns TRUE if any certificates were successfully imported.
- */
-static BOOL import_certs_from_file(int fd, HCERTSTORE store)
-{
-    BOOL ret = FALSE;
-    FILE *fp;
-
-    TRACE("\n");
-
-    fp = fdopen(fd, "r");
-    if (fp)
-    {
-        ret = import_base64_certs_from_fp(fp, store);
-        fclose(fp);
-    }
-    return ret;
-}
-
-static BOOL import_certs_from_path(LPCSTR path, HCERTSTORE store,
- BOOL allow_dir);
-
-static BOOL check_buffer_resize(char **ptr_buf, size_t *buf_size, size_t check_size)
-{
-    if (check_size > *buf_size)
-    {
-        *buf_size = check_size;
-
-        if (*ptr_buf)
-        {
-            char *realloc_buf = CryptMemRealloc(*ptr_buf, *buf_size);
-
-            if (!realloc_buf)
-                return FALSE;
-
-            *ptr_buf = realloc_buf;
-        }
-        else
-        {
-            *ptr_buf = CryptMemAlloc(*buf_size);
-            if (!*ptr_buf)
-                return FALSE;
-        }
-    }
-
-    return TRUE;
-}
-
-/* Opens path, which must be a directory, and imports certificates from every
- * file in the directory into store.
- * Returns TRUE if any certificates were successfully imported.
- */
-static BOOL import_certs_from_dir(LPCSTR path, HCERTSTORE store)
-{
-#ifdef HAVE_READDIR
-    BOOL ret = FALSE;
-    DIR *dir;
-
-    TRACE("(%s, %p)\n", debugstr_a(path), store);
-
-    dir = opendir(path);
-    if (dir)
-    {
-        size_t path_len = strlen(path), bufsize = 0;
-        char *filebuf = NULL;
-
-        struct dirent *entry;
-        while ((entry = readdir(dir)))
-        {
-            if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
-            {
-                size_t name_len = strlen(entry->d_name);
-
-                if (!check_buffer_resize(&filebuf, &bufsize, path_len + 1 + name_len + 1))
-                {
-                    ERR("Path buffer (re)allocation failed with out of memory condition\n");
-                    break;
-                }
-                snprintf(filebuf, bufsize, "%s/%s", path, entry->d_name);
-                if (import_certs_from_path(filebuf, store, FALSE) && !ret)
-                    ret = TRUE;
-            }
-        }
-        CryptMemFree(filebuf);
-        closedir(dir);
-    }
-    return ret;
-#else
-    FIXME("not implemented without readdir available\n");
-    return FALSE;
-#endif
-}
-
-/* Opens path, which may be a file or a directory, and imports any certificates
- * it finds into store.
- * Returns TRUE if any certificates were successfully imported.
- */
-static BOOL import_certs_from_path(LPCSTR path, HCERTSTORE store,
- BOOL allow_dir)
-{
-    BOOL ret = FALSE;
-    int fd;
-
-    TRACE("(%s, %p, %d)\n", debugstr_a(path), store, allow_dir);
-
-    fd = open(path, O_RDONLY);
-    if (fd != -1)
-    {
-        struct stat st;
-
-        if (fstat(fd, &st) == 0)
-        {
-            if (S_ISREG(st.st_mode))
-                ret = import_certs_from_file(fd, store);
-            else if (S_ISDIR(st.st_mode))
-            {
-                if (allow_dir)
-                    ret = import_certs_from_dir(path, store);
-                else
-                    WARN("%s is a directory and directories are disallowed\n",
-                     debugstr_a(path));
-            }
-            else
-                ERR("%s: invalid file type\n", path);
-        }
-        close(fd);
-    }
-    return ret;
-}
-
-static const char * const CRYPT_knownLocations[] = {
- "/etc/ssl/certs/ca-certificates.crt",
- "/etc/ssl/certs",
- "/etc/pki/tls/certs/ca-bundle.crt",
- "/usr/share/ca-certificates/ca-bundle.crt",
- "/usr/local/share/certs/",
- "/etc/sfw/openssl/certs",
- "/etc/security/cacerts",  /* Android */
-};
-
 static const BYTE authenticode[] = {
 0x30,0x82,0x03,0xd6,0x30,0x82,0x02,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,
@@ -879,43 +631,24 @@ static void read_trusted_roots_from_known_locations(HCERTSTORE store)
 {
     HCERTSTORE from = CertOpenStore(CERT_STORE_PROV_MEMORY,
      X509_ASN_ENCODING, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
+    SIZE_T needed, size = 2048;
+    void *buffer;
 
     if (from)
     {
-        DWORD i;
-        BOOL ret = FALSE;
-
-#ifdef HAVE_SECURITY_SECURITY_H
-        OSStatus status;
-        CFArrayRef rootCerts;
-
-        status = SecTrustCopyAnchorCertificates(&rootCerts);
-        if (status == noErr)
+        buffer = HeapAlloc( GetProcessHeap(), 0, size );
+        while (unix_funcs->enum_root_certs( buffer, size, &needed ))
         {
-            int i;
-            for (i = 0; i < CFArrayGetCount(rootCerts); i++)
+            if (needed > size)
             {
-                SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(rootCerts, i);
-                CFDataRef certData;
-                if ((status = SecKeychainItemExport(cert, kSecFormatX509Cert, 0, NULL, &certData)) == noErr)
-                {
-                    if (CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
-                            CFDataGetBytePtr(certData), CFDataGetLength(certData),
-                            CERT_STORE_ADD_NEW, NULL))
-                        ret = TRUE;
-                    else
-                        WARN("adding root cert %d failed: %08x\n", i, GetLastError());
-                    CFRelease(certData);
-                }
-                else
-                    WARN("could not export certificate %d to X509 format: 0x%08x\n", i, (unsigned int)status);
+                HeapFree( GetProcessHeap(), 0, buffer );
+                buffer = HeapAlloc( GetProcessHeap(), 0, needed );
+                size = needed;
             }
-            CFRelease(rootCerts);
+            else CertAddEncodedCertificateToStore( store, X509_ASN_ENCODING, buffer, size,
+                                                   CERT_STORE_ADD_NEW, NULL );
         }
-#endif
-
-        for (i = 0; !ret && i < ARRAY_SIZE(CRYPT_knownLocations); i++)
-            ret = import_certs_from_path(CRYPT_knownLocations[i], from, TRUE);
+        HeapFree( GetProcessHeap(), 0, buffer );
         check_and_store_certs(from, store);
     }
     CertCloseStore(from, 0);
diff --git a/dlls/crypt32/unixlib.c b/dlls/crypt32/unixlib.c
index 40c3512871104c53605633f9aeb8d0c731a39d20..47be56910054db6ff1445895248d01a7ce35b10f 100644
--- a/dlls/crypt32/unixlib.c
+++ b/dlls/crypt32/unixlib.c
@@ -24,6 +24,15 @@
 #include "wine/port.h"
 
 #include <stdarg.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SECURITY_SECURITY_H
+#include <Security/Security.h>
+#endif
 #ifdef SONAME_LIBGNUTLS
 #include <gnutls/pkcs12.h>
 #endif
@@ -297,9 +306,321 @@ error:
     return FALSE;
 }
 
-static const struct unix_funcs funcs =
+#endif /* SONAME_LIBGNUTLS */
+
+struct root_cert
+{
+    struct list entry;
+    SIZE_T      size;
+    BYTE        data[1];
+};
+
+static struct list root_cert_list = LIST_INIT(root_cert_list);
+
+static BYTE *add_cert( SIZE_T size )
+{
+    struct root_cert *cert = malloc( offsetof( struct root_cert, data[size] ));
+
+    if (!cert) return NULL;
+    cert->size = size;
+    list_add_tail( &root_cert_list, &cert->entry );
+    return cert->data;
+}
+
+struct DynamicBuffer
+{
+    DWORD allocated;
+    DWORD used;
+    char *data;
+};
+
+static inline void reset_buffer(struct DynamicBuffer *buffer)
+{
+    buffer->used = 0;
+    if (buffer->data) buffer->data[0] = 0;
+}
+
+static void add_line_to_buffer(struct DynamicBuffer *buffer, LPCSTR line)
+{
+    if (buffer->used + strlen(line) + 1 > buffer->allocated)
+    {
+        DWORD new_size = max( max( buffer->allocated * 2, 1024 ), buffer->used + strlen(line) + 1 );
+        void *ptr = realloc( buffer->data, new_size );
+        if (!ptr) return;
+        buffer->data = ptr;
+        buffer->allocated = new_size;
+        if (!buffer->used) buffer->data[0] = 0;
+    }
+    strcpy( buffer->data + buffer->used, line );
+    buffer->used += strlen(line);
+}
+
+#define BASE64_DECODE_PADDING    0x100
+#define BASE64_DECODE_WHITESPACE 0x200
+#define BASE64_DECODE_INVALID    0x300
+
+static inline int decodeBase64Byte(char c)
+{
+    int ret = BASE64_DECODE_INVALID;
+
+    if (c >= 'A' && c <= 'Z')
+        ret = c - 'A';
+    else if (c >= 'a' && c <= 'z')
+        ret = c - 'a' + 26;
+    else if (c >= '0' && c <= '9')
+        ret = c - '0' + 52;
+    else if (c == '+')
+        ret = 62;
+    else if (c == '/')
+        ret = 63;
+    else if (c == '=')
+        ret = BASE64_DECODE_PADDING;
+    else if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+        ret = BASE64_DECODE_WHITESPACE;
+    return ret;
+}
+
+static BOOL base64_to_cert( const char *str )
+{
+    DWORD i, valid, out, hasPadding;
+    BYTE block[4], *data;
+
+    for (i = valid = out = hasPadding = 0; str[i]; i++)
+    {
+        int d = decodeBase64Byte( str[i] );
+        if (d == BASE64_DECODE_INVALID) return FALSE;
+        if (d == BASE64_DECODE_WHITESPACE) continue;
+
+        /* When padding starts, data is not acceptable */
+        if (hasPadding && d != BASE64_DECODE_PADDING) return FALSE;
+
+        /* Padding after a full block (like "VVVV=") is ok and stops decoding */
+        if (d == BASE64_DECODE_PADDING && (valid & 3) == 0) break;
+
+        valid++;
+        if (d == BASE64_DECODE_PADDING)
+        {
+            hasPadding = 1;
+            /* When padding reaches a full block, stop decoding */
+            if ((valid & 3) == 0) break;
+            continue;
+        }
+
+        /* out is incremented in the 4-char block as follows: "1-23" */
+        if ((valid & 3) != 2) out++;
+    }
+    /* Fail if the block has bad padding; omitting padding is fine */
+    if ((valid & 3) != 0 && hasPadding) return FALSE;
+
+    if (!(data = add_cert( out ))) return FALSE;
+    for (i = valid = out = 0; str[i]; i++)
+    {
+        int d = decodeBase64Byte( str[i] );
+        if (d == BASE64_DECODE_WHITESPACE) continue;
+        if (d == BASE64_DECODE_PADDING) break;
+        block[valid & 3] = d;
+        valid += 1;
+        switch (valid & 3)
+        {
+        case 1:
+            data[out++] = (block[0] << 2);
+            break;
+        case 2:
+            data[out-1] = (block[0] << 2) | (block[1] >> 4);
+            break;
+        case 3:
+            data[out++] = (block[1] << 4) | (block[2] >> 2);
+            break;
+        case 0:
+            data[out++] = (block[2] << 6) | (block[3] >> 0);
+            break;
+        }
+    }
+    return TRUE;
+}
+
+/* Reads the file fd, and imports any certificates in it into store. */
+static void import_certs_from_file( int fd )
+{
+    FILE *fp = fdopen(fd, "r");
+    char line[1024];
+    BOOL in_cert = FALSE;
+    struct DynamicBuffer saved_cert = { 0, 0, NULL };
+    int num_certs = 0;
+
+    if (!fp) return;
+    TRACE("\n");
+    while (fgets(line, sizeof(line), fp))
+    {
+        static const char header[] = "-----BEGIN CERTIFICATE-----";
+        static const char trailer[] = "-----END CERTIFICATE-----";
+
+        if (!strncmp(line, header, strlen(header)))
+        {
+            TRACE("begin new certificate\n");
+            in_cert = TRUE;
+            reset_buffer(&saved_cert);
+        }
+        else if (!strncmp(line, trailer, strlen(trailer)))
+        {
+            TRACE("end of certificate, adding cert\n");
+            in_cert = FALSE;
+            if (base64_to_cert( saved_cert.data )) num_certs++;
+        }
+        else if (in_cert) add_line_to_buffer(&saved_cert, line);
+    }
+    free( saved_cert.data );
+    TRACE("Read %d certs\n", num_certs);
+    fclose(fp);
+}
+
+static void import_certs_from_path(LPCSTR path, BOOL allow_dir);
+
+static BOOL check_buffer_resize(char **ptr_buf, size_t *buf_size, size_t check_size)
+{
+    if (check_size > *buf_size)
+    {
+        void *ptr = realloc(*ptr_buf, check_size);
+
+        if (!ptr) return FALSE;
+        *buf_size = check_size;
+        *ptr_buf = ptr;
+    }
+    return TRUE;
+}
+
+/* Opens path, which must be a directory, and imports certificates from every
+ * file in the directory into store.
+ * Returns TRUE if any certificates were successfully imported.
+ */
+static void import_certs_from_dir( LPCSTR path )
+{
+    DIR *dir;
+
+    dir = opendir(path);
+    if (dir)
+    {
+        size_t path_len = strlen(path), bufsize = 0;
+        char *filebuf = NULL;
+
+        struct dirent *entry;
+        while ((entry = readdir(dir)))
+        {
+            if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
+            {
+                size_t name_len = strlen(entry->d_name);
+
+                if (!check_buffer_resize(&filebuf, &bufsize, path_len + 1 + name_len + 1)) break;
+                snprintf(filebuf, bufsize, "%s/%s", path, entry->d_name);
+                import_certs_from_path(filebuf, FALSE);
+            }
+        }
+        free(filebuf);
+        closedir(dir);
+    }
+}
+
+/* Opens path, which may be a file or a directory, and imports any certificates
+ * it finds into store.
+ * Returns TRUE if any certificates were successfully imported.
+ */
+static void import_certs_from_path(LPCSTR path, BOOL allow_dir)
+{
+    int fd;
+
+    TRACE("(%s, %d)\n", debugstr_a(path), allow_dir);
+
+    fd = open(path, O_RDONLY);
+    if (fd != -1)
+    {
+        struct stat st;
+
+        if (fstat(fd, &st) == 0)
+        {
+            if (S_ISREG(st.st_mode))
+                import_certs_from_file(fd);
+            else if (S_ISDIR(st.st_mode))
+            {
+                if (allow_dir)
+                    import_certs_from_dir(path);
+                else
+                    WARN("%s is a directory and directories are disallowed\n",
+                     debugstr_a(path));
+            }
+            else
+                ERR("%s: invalid file type\n", path);
+        }
+        close(fd);
+    }
+}
+
+static const char * const CRYPT_knownLocations[] = {
+ "/etc/ssl/certs/ca-certificates.crt",
+ "/etc/ssl/certs",
+ "/etc/pki/tls/certs/ca-bundle.crt",
+ "/usr/share/ca-certificates/ca-bundle.crt",
+ "/usr/local/share/certs/",
+ "/etc/sfw/openssl/certs",
+ "/etc/security/cacerts",  /* Android */
+};
+
+static void load_root_certs(void)
+{
+    DWORD i;
+
+#ifdef HAVE_SECURITY_SECURITY_H
+    OSStatus status;
+    CFArrayRef rootCerts;
+
+    status = SecTrustCopyAnchorCertificates(&rootCerts);
+    if (status == noErr)
+    {
+        for (i = 0; i < CFArrayGetCount(rootCerts); i++)
+        {
+            SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(rootCerts, i);
+            CFDataRef certData;
+            if ((status = SecKeychainItemExport(cert, kSecFormatX509Cert, 0, NULL, &certData)) == noErr)
+            {
+                BYTE *data = add_cert( CFDataGetLength(certData) );
+                if (data) memcpy( data, CFDataGetBytePtr(certData), CFDataGetLength(certData) );
+                CFRelease(certData);
+            }
+            else
+                WARN("could not export certificate %d to X509 format: 0x%08x\n", i, (unsigned int)status);
+        }
+        CFRelease(rootCerts);
+    }
+#endif
+
+    for (i = 0; i < ARRAY_SIZE(CRYPT_knownLocations) && list_empty(&root_cert_list); i++)
+        import_certs_from_path( CRYPT_knownLocations[i], TRUE );
+}
+
+static BOOL WINAPI enum_root_certs( void *buffer, SIZE_T size, SIZE_T *needed )
 {
-    import_cert_store
+    static BOOL loaded;
+    struct list *ptr;
+    struct root_cert *cert;
+
+    if (!loaded) load_root_certs();
+    loaded = TRUE;
+
+    if (!(ptr = list_head( &root_cert_list ))) return FALSE;
+    cert = LIST_ENTRY( ptr, struct root_cert, entry );
+    *needed = cert->size;
+    if (cert->size <= size)
+    {
+        memcpy( buffer, cert->data, cert->size );
+        list_remove( &cert->entry );
+        free( cert );
+    }
+    return TRUE;
+}
+
+static struct unix_funcs funcs =
+{
+    enum_root_certs,
+    NULL
 };
 
 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
@@ -307,14 +628,16 @@ NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *p
     switch (reason)
     {
     case DLL_PROCESS_ATTACH:
-        if (!gnutls_initialize()) return STATUS_DLL_NOT_FOUND;
+#ifdef SONAME_LIBGNUTLS
+        if (gnutls_initialize()) funcs.import_cert_store = import_cert_store;
+#endif
         *(const struct unix_funcs **)ptr_out = &funcs;
         break;
     case DLL_PROCESS_DETACH:
+#ifdef SONAME_LIBGNUTLS
         if (libgnutls_handle) gnutls_uninitialize();
+#endif
         break;
     }
     return STATUS_SUCCESS;
 }
-
-#endif /* SONAME_LIBGNUTLS */