]> git.eshelyaron.com Git - emacs.git/commitdiff
Implement dynamic loading of GnuTLS on Windows.
authorJuanma Barranquero <lekktu@gmail.com>
Wed, 4 May 2011 14:03:16 +0000 (16:03 +0200)
committerJuanma Barranquero <lekktu@gmail.com>
Wed, 4 May 2011 14:03:16 +0000 (16:03 +0200)
* lisp/term/w32-win.el (dynamic-library-alist): Add `gnutls'.

* nt/INSTALL: Clarify GnuTLS support.

* src/callproc.c, src/emacs.c: Include lisp.h before src/w32.h, not after.

* src/gnutls.c (Qgnutls_dll): Define.
  (DEF_GNUTLS_FN, LOAD_GNUTLS_FN): New macros.
  (gnutls_*): Declare function pointers.
  (init_gnutls_functions): New function to initialize function pointers.
  (emacs_gnutls_handshake, Fgnutls_error_string, Fgnutls_deinit)
  (emacs_gnutls_global_init, Fgnutls_bye): Use function pointers.
  (emacs_gnutls_record_check_pending, emacs_gnutls_transport_set_errno):
  Wrappers for gnutls_record_check_pending and gnutls_transport_set_errno.
  (emacs_gnutls_write, emacs_gnutls_read)
  (emacs_gnutls_handle_error, Fgnutls_error_fatalp)
  (Fgnutls_available_p): New function.
  (Fgnutls_boot): Call Fgnutls_available_p.  Use function pointers.
  (syms_of_gnutls) <Qgnutls_dll>: Initialize and staticpro it.
  (syms_of_gnutls) <Sgnutls_available_p>: defsubr it.

* src/gnutls.h (GNUTLS_EMACS_ERROR_NOT_LOADED): New macro.
  (emacs_gnutls_write, emacs_gnutls_read): Mark as extern.
  (emacs_gnutls_record_check_pending, emacs_gnutls_transport_set_errno):
  Declare.

* src/w32.c (QCloaded_from, Vlibrary_cache): Define.
  (w32_delayed_load): Move from image.c.  When loading a library, record
  its filename in the :loaded-from property of the library id.
  (globals_of_w32) <QCloaded_from, Vlibrary_cache>:
  Initialize and staticpro them.
  (emacs_gnutls_pull, emacs_gnutls_push): Call emacs_gnutls_* functions.

* src/image.c: Include w32.h.
  (Vimage_type_cache): Delete.
  (syms_of_image) <Vimage_type_cache>: Don't initialize and staticpro it.
  (CACHE_IMAGE_TYPE, Finit_image_library): Use Vlibrary_cache instead.
  (w32_delayed_load): Move to w32.c.

* src/process.c: Include lisp.h before src/w32.h, not after.
  (wait_reading_process_output): Call emacs_gnutls_record_check_pending
  instead of gnutls_record_check_pending.

* src/w32.h (VlibraryCache, QCloaded_from, w32_delayed_load): Declare.

13 files changed:
lisp/ChangeLog
lisp/term/w32-win.el
nt/ChangeLog
nt/INSTALL
src/ChangeLog
src/callproc.c
src/emacs.c
src/gnutls.c
src/gnutls.h
src/image.c
src/process.c
src/w32.c
src/w32.h

index 3d7b2c338322a16cc2aad4d3b6bf9fdf9088b4d2..4f6ebe882770af974bbf7ed278dfa1be05b9c468 100644 (file)
@@ -1,3 +1,7 @@
+2011-05-04  Juanma Barranquero  <lekktu@gmail.com>
+
+       * term/w32-win.el (dynamic-library-alist): Add `gnutls'.
+
 2011-05-04  Glenn Morris  <rgm@gnu.org>
 
        * calendar/diary-lib.el (diary-fancy-date-pattern): Turn it into a
index f1385a9645cae7e578d92f4c30b1ce2178535eed..e4bf031d4221d505262c5fe15da8bb9ee46ab042 100644 (file)
@@ -202,13 +202,14 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
         '(png "libpng12d.dll" "libpng12.dll" "libpng3.dll" "libpng.dll"
               ;; these are libpng 1.2.8 from GTK+
               "libpng13d.dll" "libpng13.dll"))
-        '(jpeg "jpeg62.dll" "libjpeg.dll" "jpeg-62.dll" "jpeg.dll")
-        '(tiff "libtiff3.dll" "libtiff.dll")
-        '(gif "giflib4.dll" "libungif4.dll" "libungif.dll")
-        '(svg "librsvg-2-2.dll")
-        '(gdk-pixbuf "libgdk_pixbuf-2.0-0.dll")
-        '(glib "libglib-2.0-0.dll")
-       '(gobject "libgobject-2.0-0.dll")))
+       '(jpeg "jpeg62.dll" "libjpeg.dll" "jpeg-62.dll" "jpeg.dll")
+       '(tiff "libtiff3.dll" "libtiff.dll")
+       '(gif "giflib4.dll" "libungif4.dll" "libungif.dll")
+       '(svg "librsvg-2-2.dll")
+       '(gdk-pixbuf "libgdk_pixbuf-2.0-0.dll")
+       '(glib "libglib-2.0-0.dll")
+       '(gobject "libgobject-2.0-0.dll")
+       '(gnutls "libgnutls-26.dll")))
 
 ;;; multi-tty support
 (defvar w32-initialized nil
index 660140f66cfffa42b023139291756745aee42968..83080273f5ba2c18dea30859179f63c0830c9339 100644 (file)
@@ -1,3 +1,7 @@
+2011-05-04  Juanma Barranquero  <lekktu@gmail.com>
+
+       * INSTALL: Clarify GnuTLS support.
+
 2011-04-30  Eli Zaretskii  <eliz@gnu.org>
 
        * config.nt (HAVE_LONG_LONG_INT, HAVE_UNSIGNED_LONG_LONG_INT):
index dc57cd20b8cd185b708374602ce0e55087d54a16..2a1a9aaab12885365112c6d9ecb27a9759297b0f 100644 (file)
 
 * Optional GnuTLS support
 
-  You can build Emacs with GnuTLS support.  Put the gnutls/gnutls.h header in
-  the include path and link to the appropriate libraries (gnutls.dll and
-  gcrypt.dll) with the --lib option.
+  If configure.bat finds the gnutls/gnutls.h file in the include path,
+  Emacs is built with GnuTLS support by default; to avoid that you can
+  pass the argument --without-gnutls.
 
-  You can get pre-built binaries and an installer at
-  http://josefsson.org/gnutls4win/.
+  In order to support GnuTLS at runtime, a GnuTLS-enabled Emacs must
+  be able to find the relevant DLLs during startup; failure to do so
+  is not an error, but GnuTLS won't be available to the running
+  session.
+
+  You can get pre-built binaries (including any required DLL and the
+  gnutls.h file) and an installer at http://josefsson.org/gnutls4win/.
 
 * Experimental SVG support
 
index bc6b89f14501307c5e24f9e00cf359ee51669936..9e1705339de4d31e6a61b40d676b3fd549f0ff4b 100644 (file)
@@ -1,3 +1,48 @@
+2011-05-04  Juanma Barranquero  <lekktu@gmail.com>
+
+       Implement dynamic loading of GnuTLS on Windows.
+
+       * gnutls.h (GNUTLS_EMACS_ERROR_NOT_LOADED): New macro.
+       (emacs_gnutls_write, emacs_gnutls_read): Mark as extern.
+       (emacs_gnutls_record_check_pending, emacs_gnutls_transport_set_errno):
+       Declare.
+
+       * gnutls.c (Qgnutls_dll): Define.
+       (DEF_GNUTLS_FN, LOAD_GNUTLS_FN): New macros.
+       (gnutls_*): Declare function pointers.
+       (init_gnutls_functions): New function to initialize function pointers.
+       (emacs_gnutls_handshake, Fgnutls_error_string, Fgnutls_deinit)
+       (emacs_gnutls_global_init, Fgnutls_bye): Use function pointers.
+       (emacs_gnutls_record_check_pending, emacs_gnutls_transport_set_errno):
+       Wrappers for gnutls_record_check_pending and gnutls_transport_set_errno.
+       (emacs_gnutls_write, emacs_gnutls_read)
+       (emacs_gnutls_handle_error, Fgnutls_error_fatalp)
+       (Fgnutls_available_p): New function.
+       (Fgnutls_boot): Call Fgnutls_available_p.  Use function pointers.
+       (syms_of_gnutls) <Qgnutls_dll>: Initialize and staticpro it.
+       (syms_of_gnutls) <Sgnutls_available_p>: defsubr it.
+
+       * image.c: Include w32.h.
+       (Vimage_type_cache): Delete.
+       (syms_of_image) <Vimage_type_cache>: Don't initialize and staticpro it.
+       (CACHE_IMAGE_TYPE, Finit_image_library): Use Vlibrary_cache instead.
+       (w32_delayed_load): Move to w32.c.
+
+       * w32.h (VlibraryCache, QCloaded_from, w32_delayed_load): Declare.
+
+       * w32.c (QCloaded_from, Vlibrary_cache): Define.
+       (w32_delayed_load): Move from image.c.  When loading a library, record
+       its filename in the :loaded-from property of the library id.
+       (globals_of_w32) <QCloaded_from, Vlibrary_cache>:
+       Initialize and staticpro them.
+       (emacs_gnutls_pull, emacs_gnutls_push): Call emacs_gnutls_* functions.
+
+       * process.c: Include lisp.h before w32.h, not after.
+       (wait_reading_process_output): Call emacs_gnutls_record_check_pending
+       instead of gnutls_record_check_pending.
+
+       * callproc.c, emacs.c: Include lisp.h before w32.h, not after.
+
 2011-05-04  Teodor Zlatanov  <tzz@lifelogs.com>
 
        * gnutls.c (Fgnutls_boot): Support :keylist and :crlfiles options
index 4a29e95b356c94b052d826f410a81681b065444b..1d3d8764ff88d050f05c6469ebaa840ea7302d08 100644 (file)
@@ -29,6 +29,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/file.h>
 #include <fcntl.h>
 
+#include "lisp.h"
+
 #ifdef WINDOWSNT
 #define NOMINMAX
 #include <windows.h>
@@ -41,7 +43,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/param.h>
 #endif /* MSDOS */
 
-#include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
 #include "character.h"
index 0a132e156a01e11910fdfd97d89fd2ac7152312d..8c4490b0a523aedefe5fea549bd6d7d2bf13070e 100644 (file)
@@ -29,6 +29,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <setjmp.h>
 #include <unistd.h>
 
+#include "lisp.h"
+
 #ifdef WINDOWSNT
 #include <fcntl.h>
 #include <windows.h> /* just for w32.h */
@@ -41,7 +43,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <GNUstepBase/GSConfig.h>
 #endif
 
-#include "lisp.h"
 #include "commands.h"
 #include "intervals.h"
 #include "buffer.h"
index fd970910d24c29308b0a81d9284120d42e5d05e3..7e821ccd41d8b68bc61b765e121b73053b5bda2f 100644 (file)
@@ -34,6 +34,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 static int
 emacs_gnutls_handle_error (gnutls_session_t, int err);
 
+static Lisp_Object Qgnutls_dll;
 static Lisp_Object Qgnutls_log_level;
 static Lisp_Object Qgnutls_code;
 static Lisp_Object Qgnutls_anon, Qgnutls_x509pki;
@@ -56,6 +57,181 @@ static Lisp_Object Qgnutls_bootprop_verify_hostname_error;
 /* Callback keys for `gnutls-boot'.  Unused currently.  */
 static Lisp_Object Qgnutls_bootprop_callbacks_verify;
 
+static void gnutls_log_function (int, const char *);
+static void gnutls_log_function2 (int, const char*, const char*);
+
+\f
+#ifdef WINDOWSNT
+
+/* Macro for defining functions that will be loaded from the GnuTLS DLL.  */
+#define DEF_GNUTLS_FN(rettype,func,args) rettype (FAR CDECL *fn_##func)args
+
+/* Macro for loading GnuTLS functions from the library.  */
+#define LOAD_GNUTLS_FN(lib,func) {                                     \
+    fn_##func = (void *) GetProcAddress (lib, #func);                  \
+    if (!fn_##func) return 0;                                          \
+  }
+
+DEF_GNUTLS_FN (gnutls_alert_description_t, gnutls_alert_get,
+               (gnutls_session_t));
+DEF_GNUTLS_FN (const char *, gnutls_alert_get_name,
+               (gnutls_alert_description_t));
+DEF_GNUTLS_FN (int, gnutls_alert_send_appropriate, (gnutls_session_t, int));
+DEF_GNUTLS_FN (int, gnutls_anon_allocate_client_credentials,
+               (gnutls_anon_client_credentials_t *));
+DEF_GNUTLS_FN (void, gnutls_anon_free_client_credentials,
+               (gnutls_anon_client_credentials_t));
+DEF_GNUTLS_FN (int, gnutls_bye, (gnutls_session_t, gnutls_close_request_t));
+DEF_GNUTLS_FN (int, gnutls_certificate_allocate_credentials,
+               (gnutls_certificate_credentials_t *));
+DEF_GNUTLS_FN (void, gnutls_certificate_free_credentials,
+               (gnutls_certificate_credentials_t));
+DEF_GNUTLS_FN (const gnutls_datum_t *, gnutls_certificate_get_peers,
+               (gnutls_session_t, unsigned int *));
+DEF_GNUTLS_FN (void, gnutls_certificate_set_verify_flags,
+               (gnutls_certificate_credentials_t, unsigned int));
+DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_crl_file,
+               (gnutls_certificate_credentials_t, const char *,
+                gnutls_x509_crt_fmt_t));
+DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_key_file,
+               (gnutls_certificate_credentials_t, const char *, const char *,
+                gnutls_x509_crt_fmt_t));
+DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_trust_file,
+               (gnutls_certificate_credentials_t, const char *,
+                gnutls_x509_crt_fmt_t));
+DEF_GNUTLS_FN (gnutls_certificate_type_t, gnutls_certificate_type_get,
+               (gnutls_session_t));
+DEF_GNUTLS_FN (int, gnutls_certificate_verify_peers2,
+               (gnutls_session_t, unsigned int *));
+DEF_GNUTLS_FN (int, gnutls_credentials_set,
+               (gnutls_session_t, gnutls_credentials_type_t, void *));
+DEF_GNUTLS_FN (void, gnutls_deinit, (gnutls_session_t));
+DEF_GNUTLS_FN (int, gnutls_error_is_fatal, (int));
+DEF_GNUTLS_FN (int, gnutls_global_init, (void));
+DEF_GNUTLS_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
+DEF_GNUTLS_FN (void, gnutls_global_set_log_level, (int));
+DEF_GNUTLS_FN (int, gnutls_handshake, (gnutls_session_t));
+DEF_GNUTLS_FN (int, gnutls_init, (gnutls_session_t *, gnutls_connection_end_t));
+DEF_GNUTLS_FN (int, gnutls_priority_set_direct,
+               (gnutls_session_t, const char *, const char **));
+DEF_GNUTLS_FN (size_t, gnutls_record_check_pending, (gnutls_session_t));
+DEF_GNUTLS_FN (ssize_t, gnutls_record_recv, (gnutls_session_t, void *, size_t));
+DEF_GNUTLS_FN (ssize_t, gnutls_record_send,
+               (gnutls_session_t, const void *, size_t));
+DEF_GNUTLS_FN (const char *, gnutls_strerror, (int));
+DEF_GNUTLS_FN (void, gnutls_transport_set_errno, (gnutls_session_t, int));
+DEF_GNUTLS_FN (void, gnutls_transport_set_lowat, (gnutls_session_t, int));
+DEF_GNUTLS_FN (void, gnutls_transport_set_ptr2,
+               (gnutls_session_t, gnutls_transport_ptr_t,
+                gnutls_transport_ptr_t));
+DEF_GNUTLS_FN (void, gnutls_transport_set_pull_function,
+               (gnutls_session_t, gnutls_pull_func));
+DEF_GNUTLS_FN (void, gnutls_transport_set_push_function,
+               (gnutls_session_t, gnutls_push_func));
+DEF_GNUTLS_FN (int, gnutls_x509_crt_check_hostname,
+               (gnutls_x509_crt_t, const char *));
+DEF_GNUTLS_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t));
+DEF_GNUTLS_FN (int, gnutls_x509_crt_import,
+               (gnutls_x509_crt_t, const gnutls_datum_t *,
+                gnutls_x509_crt_fmt_t));
+DEF_GNUTLS_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *));
+
+static int
+init_gnutls_functions (Lisp_Object libraries)
+{
+  HMODULE library;
+
+  if (!(library = w32_delayed_load (libraries, Qgnutls_dll)))
+    {
+      GNUTLS_LOG (1, 1, "GnuTLS library not found");
+      return 0;
+    }
+
+  LOAD_GNUTLS_FN (library, gnutls_alert_get);
+  LOAD_GNUTLS_FN (library, gnutls_alert_get_name);
+  LOAD_GNUTLS_FN (library, gnutls_alert_send_appropriate);
+  LOAD_GNUTLS_FN (library, gnutls_anon_allocate_client_credentials);
+  LOAD_GNUTLS_FN (library, gnutls_anon_free_client_credentials);
+  LOAD_GNUTLS_FN (library, gnutls_bye);
+  LOAD_GNUTLS_FN (library, gnutls_certificate_allocate_credentials);
+  LOAD_GNUTLS_FN (library, gnutls_certificate_free_credentials);
+  LOAD_GNUTLS_FN (library, gnutls_certificate_get_peers);
+  LOAD_GNUTLS_FN (library, gnutls_certificate_set_verify_flags);
+  LOAD_GNUTLS_FN (library, gnutls_certificate_set_x509_crl_file);
+  LOAD_GNUTLS_FN (library, gnutls_certificate_set_x509_key_file);
+  LOAD_GNUTLS_FN (library, gnutls_certificate_set_x509_trust_file);
+  LOAD_GNUTLS_FN (library, gnutls_certificate_type_get);
+  LOAD_GNUTLS_FN (library, gnutls_certificate_verify_peers2);
+  LOAD_GNUTLS_FN (library, gnutls_credentials_set);
+  LOAD_GNUTLS_FN (library, gnutls_deinit);
+  LOAD_GNUTLS_FN (library, gnutls_error_is_fatal);
+  LOAD_GNUTLS_FN (library, gnutls_global_init);
+  LOAD_GNUTLS_FN (library, gnutls_global_set_log_function);
+  LOAD_GNUTLS_FN (library, gnutls_global_set_log_level);
+  LOAD_GNUTLS_FN (library, gnutls_handshake);
+  LOAD_GNUTLS_FN (library, gnutls_init);
+  LOAD_GNUTLS_FN (library, gnutls_priority_set_direct);
+  LOAD_GNUTLS_FN (library, gnutls_record_check_pending);
+  LOAD_GNUTLS_FN (library, gnutls_record_recv);
+  LOAD_GNUTLS_FN (library, gnutls_record_send);
+  LOAD_GNUTLS_FN (library, gnutls_strerror);
+  LOAD_GNUTLS_FN (library, gnutls_transport_set_errno);
+  LOAD_GNUTLS_FN (library, gnutls_transport_set_lowat);
+  LOAD_GNUTLS_FN (library, gnutls_transport_set_ptr2);
+  LOAD_GNUTLS_FN (library, gnutls_transport_set_pull_function);
+  LOAD_GNUTLS_FN (library, gnutls_transport_set_push_function);
+  LOAD_GNUTLS_FN (library, gnutls_x509_crt_check_hostname);
+  LOAD_GNUTLS_FN (library, gnutls_x509_crt_deinit);
+  LOAD_GNUTLS_FN (library, gnutls_x509_crt_import);
+  LOAD_GNUTLS_FN (library, gnutls_x509_crt_init);
+
+  GNUTLS_LOG2 (1, 1, "GnuTLS library loaded:",
+               SDATA (Fget (Qgnutls_dll, QCloaded_from)));
+  return 1;
+}
+
+#else /* !WINDOWSNT */
+
+#define fn_gnutls_alert_get                    gnutls_alert_get
+#define fn_gnutls_alert_get_name               gnutls_alert_get_name
+#define fn_gnutls_alert_send_appropriate       gnutls_alert_send_appropriate
+#define fn_gnutls_anon_allocate_client_credentials gnutls_anon_allocate_client_credentials
+#define fn_gnutls_anon_free_client_credentials gnutls_anon_free_client_credentials
+#define fn_gnutls_bye                          gnutls_bye
+#define fn_gnutls_certificate_allocate_credentials gnutls_certificate_allocate_credentials
+#define fn_gnutls_certificate_free_credentials gnutls_certificate_free_credentials
+#define fn_gnutls_certificate_get_peers                gnutls_certificate_get_peers
+#define fn_gnutls_certificate_set_verify_flags gnutls_certificate_set_verify_flags
+#define fn_gnutls_certificate_set_x509_crl_file        gnutls_certificate_set_x509_crl_file
+#define fn_gnutls_certificate_set_x509_trust_file gnutls_certificate_set_x509_trust_file
+#define fn_gnutls_certificate_type_get         gnutls_certificate_type_get
+#define fn_gnutls_certificate_verify_peers2    gnutls_certificate_verify_peers2
+#define fn_gnutls_credentials_set              gnutls_credentials_set
+#define fn_gnutls_deinit                       gnutls_deinit
+#define fn_gnutls_error_is_fatal               gnutls_error_is_fatal
+#define fn_gnutls_global_init                  gnutls_global_init
+#define fn_gnutls_global_set_log_function      gnutls_global_set_log_function
+#define fn_gnutls_global_set_log_level         gnutls_global_set_log_level
+#define fn_gnutls_handshake                    gnutls_handshake
+#define fn_gnutls_init                         gnutls_init
+#define fn_gnutls_priority_set_direct          gnutls_priority_set_direct
+#define fn_gnutls_record_check_pending         gnutls_record_check_pending
+#define fn_gnutls_record_recv                  gnutls_record_recv
+#define fn_gnutls_record_send                  gnutls_record_send
+#define fn_gnutls_strerror                     gnutls_strerror
+#define fn_gnutls_transport_set_errno          gnutls_transport_set_errno
+#define fn_gnutls_transport_set_lowat          gnutls_transport_set_lowat
+#define fn_gnutls_transport_set_ptr2           gnutls_transport_set_ptr2
+#define fn_gnutls_transport_set_pull_function  gnutls_transport_set_pull_function
+#define fn_gnutls_transport_set_push_function  gnutls_transport_set_push_function
+#define fn_gnutls_x509_crt_check_hostname      gnutls_x509_crt_check_hostname
+#define fn_gnutls_x509_crt_deinit              gnutls_x509_crt_deinit
+#define fn_gnutls_x509_crt_import              gnutls_x509_crt_import
+#define fn_gnutls_x509_crt_init                        gnutls_x509_crt_init
+
+#endif /* !WINDOWSNT */
+
+\f
 static void
 gnutls_log_function (int level, const char* string)
 {
@@ -83,11 +259,11 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
       /* On W32 we cannot transfer socket handles between different runtime
          libraries, so we tell GnuTLS to use our special push/pull
          functions.  */
-      gnutls_transport_set_ptr2 (state,
-                                 (gnutls_transport_ptr_t) proc,
-                                 (gnutls_transport_ptr_t) proc);
-      gnutls_transport_set_push_function (state, &emacs_gnutls_push);
-      gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
+      fn_gnutls_transport_set_ptr2 (state,
+                                    (gnutls_transport_ptr_t) proc,
+                                    (gnutls_transport_ptr_t) proc);
+      fn_gnutls_transport_set_push_function (state, &emacs_gnutls_push);
+      fn_gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
 
       /* For non blocking sockets or other custom made pull/push
          functions the gnutls_transport_set_lowat must be called, with
@@ -96,14 +272,14 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
          (Note: this is probably not strictly necessary as the lowat
           value is only used when no custom pull/push functions are
           set.)  */
-      gnutls_transport_set_lowat (state, 0);
+      fn_gnutls_transport_set_lowat (state, 0);
 #else
       /* This is how GnuTLS takes sockets: as file descriptors passed
          in.  For an Emacs process socket, infd and outfd are the
          same but we use this two-argument version for clarity.  */
-      gnutls_transport_set_ptr2 (state,
-                                (gnutls_transport_ptr_t) (long) proc->infd,
-                                (gnutls_transport_ptr_t) (long) proc->outfd);
+      fn_gnutls_transport_set_ptr2 (state,
+                                    (gnutls_transport_ptr_t) (long) proc->infd,
+                                    (gnutls_transport_ptr_t) (long) proc->outfd);
 #endif
 
       proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
@@ -111,10 +287,10 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
 
   do
     {
-      ret = gnutls_handshake (state);
+      ret = fn_gnutls_handshake (state);
       emacs_gnutls_handle_error (state, ret);
     }
-  while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
+  while (ret < 0 && fn_gnutls_error_is_fatal (ret) == 0);
 
   proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED;
 
@@ -125,11 +301,23 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
     }
   else
     {
-        gnutls_alert_send_appropriate (state, ret);
+      fn_gnutls_alert_send_appropriate (state, ret);
     }
   return ret;
 }
 
+int
+emacs_gnutls_record_check_pending (gnutls_session_t state)
+{
+  return fn_gnutls_record_check_pending (state);
+}
+
+void
+emacs_gnutls_transport_set_errno (gnutls_session_t state, int err)
+{
+  fn_gnutls_transport_set_errno (state, err);
+}
+
 EMACS_INT
 emacs_gnutls_write (int fildes, struct Lisp_Process *proc, const char *buf,
                     EMACS_INT nbyte)
@@ -152,7 +340,7 @@ emacs_gnutls_write (int fildes, struct Lisp_Process *proc, const char *buf,
 
   while (nbyte > 0)
     {
-      rtnval = gnutls_write (state, buf, nbyte);
+      rtnval = fn_gnutls_record_send (state, buf, nbyte);
 
       if (rtnval < 0)
         {
@@ -183,7 +371,7 @@ emacs_gnutls_read (int fildes, struct Lisp_Process *proc, char *buf,
       emacs_gnutls_handshake (proc);
       return -1;
     }
-  rtnval = gnutls_read (state, buf, nbyte);
+  rtnval = fn_gnutls_record_recv (state, buf, nbyte);
   if (rtnval >= 0)
     return rtnval;
   else if (emacs_gnutls_handle_error (state, rtnval) == 0)
@@ -215,11 +403,11 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
 
   /* TODO: use gnutls-error-fatalp and gnutls-error-string.  */
 
-  str = gnutls_strerror (err);
+  str = fn_gnutls_strerror (err);
   if (!str)
     str = "unknown";
 
-  if (gnutls_error_is_fatal (err))
+  if (fn_gnutls_error_is_fatal (err))
     {
       ret = err;
       GNUTLS_LOG2 (0, max_log_level, "fatal error:", str);
@@ -234,9 +422,9 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
   if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
       || err == GNUTLS_E_FATAL_ALERT_RECEIVED)
     {
-      int alert = gnutls_alert_get (session);
+      int alert = fn_gnutls_alert_get (session);
       int level = (err == GNUTLS_E_FATAL_ALERT_RECEIVED) ? 0 : 1;
-      str = gnutls_alert_get_name (alert);
+      str = fn_gnutls_alert_get_name (alert);
       if (!str)
        str = "unknown";
 
@@ -314,7 +502,7 @@ usage: (gnutls-error-fatalp ERROR)  */)
   if (!NUMBERP (err))
     error ("Not an error symbol or code");
 
-  if (0 == gnutls_error_is_fatal (XINT (err)))
+  if (0 == fn_gnutls_error_is_fatal (XINT (err)))
     return Qnil;
 
   return Qt;
@@ -346,7 +534,7 @@ usage: (gnutls-error-string ERROR)  */)
   if (!NUMBERP (err))
     return build_string ("Not an error symbol or code");
 
-  return build_string (gnutls_strerror (XINT (err)));
+  return build_string (fn_gnutls_strerror (XINT (err)));
 }
 
 DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
@@ -361,13 +549,34 @@ See also `gnutls-init'.  */)
 
   if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT)
     {
-      gnutls_deinit (state);
+      fn_gnutls_deinit (state);
       GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1;
     }
 
   return Qt;
 }
 
+DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
+       doc: /* Return t if GnuTLS is available in this instance of Emacs.  */)
+     (void)
+{
+#ifdef WINDOWSNT
+  Lisp_Object found = Fassq (Qgnutls_dll, Vlibrary_cache);
+  if (CONSP (found))
+    return XCDR (found);
+  else
+    {
+      Lisp_Object status;
+      status = init_gnutls_functions (Vdynamic_library_alist) ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qgnutls_dll, status), Vlibrary_cache);
+      return status;
+    }
+#else
+  return Qt;
+#endif
+}
+
+
 /* Initializes global GnuTLS state to defaults.
 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
 Returns zero on success.  */
@@ -377,8 +586,7 @@ emacs_gnutls_global_init (void)
   int ret = GNUTLS_E_SUCCESS;
 
   if (!gnutls_global_initialized)
-    ret = gnutls_global_init ();
-
+    ret = fn_gnutls_global_init ();
   gnutls_global_initialized = 1;
 
   return gnutls_make_error (ret);
@@ -488,6 +696,12 @@ one trustfile (usually a CA bundle).  */)
   CHECK_SYMBOL (type);
   CHECK_LIST (proplist);
 
+  if (NILP (Fgnutls_available_p ()))
+    {
+      error ("GnuTLS not available");
+      return gnutls_make_error (GNUTLS_EMACS_ERROR_NOT_LOADED);
+    }
+
   hostname              = Fplist_get (proplist, Qgnutls_bootprop_hostname);
   priority_string       = Fplist_get (proplist, Qgnutls_bootprop_priority);
   trustfiles            = Fplist_get (proplist, Qgnutls_bootprop_trustfiles);
@@ -509,8 +723,8 @@ one trustfile (usually a CA bundle).  */)
 
   if (NUMBERP (loglevel))
     {
-      gnutls_global_set_log_function (gnutls_log_function);
-      gnutls_global_set_log_level (XINT (loglevel));
+      fn_gnutls_global_set_log_function (gnutls_log_function);
+      fn_gnutls_global_set_log_level (XINT (loglevel));
       max_log_level = XINT (loglevel);
       XPROCESS (proc)->gnutls_log_level = max_log_level;
     }
@@ -529,13 +743,13 @@ one trustfile (usually a CA bundle).  */)
        {
           GNUTLS_LOG (2, max_log_level, "deallocating x509 credentials");
           x509_cred = XPROCESS (proc)->gnutls_x509_cred;
-          gnutls_certificate_free_credentials (x509_cred);
+          fn_gnutls_certificate_free_credentials (x509_cred);
        }
       else if (EQ (type, Qgnutls_anon))
        {
           GNUTLS_LOG (2, max_log_level, "deallocating anon credentials");
           anon_cred = XPROCESS (proc)->gnutls_anon_cred;
-          gnutls_anon_free_client_credentials (anon_cred);
+          fn_gnutls_anon_free_client_credentials (anon_cred);
        }
       else
        {
@@ -558,7 +772,7 @@ one trustfile (usually a CA bundle).  */)
     {
       GNUTLS_LOG (2, max_log_level, "allocating x509 credentials");
       x509_cred = XPROCESS (proc)->gnutls_x509_cred;
-      if (gnutls_certificate_allocate_credentials (&x509_cred) < 0)
+      if (fn_gnutls_certificate_allocate_credentials (&x509_cred) < 0)
         memory_full ();
 
       if (NUMBERP (verify_flags))
@@ -576,13 +790,13 @@ one trustfile (usually a CA bundle).  */)
           /* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT.  */
           GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags");
         }
-      gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
+      fn_gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
     }
   else if (EQ (type, Qgnutls_anon))
     {
       GNUTLS_LOG (2, max_log_level, "allocating anon credentials");
       anon_cred = XPROCESS (proc)->gnutls_anon_cred;
-      if (gnutls_anon_allocate_client_credentials (&anon_cred) < 0)
+      if (fn_gnutls_anon_allocate_client_credentials (&anon_cred) < 0)
         memory_full ();
     }
   else
@@ -605,7 +819,7 @@ one trustfile (usually a CA bundle).  */)
             {
               GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
                            SSDATA (trustfile));
-              ret = gnutls_certificate_set_x509_trust_file
+              ret = fn_gnutls_certificate_set_x509_trust_file
                 (x509_cred,
                  SSDATA (trustfile),
                  file_format);
@@ -627,7 +841,7 @@ one trustfile (usually a CA bundle).  */)
             {
               GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
                            SSDATA (crlfile));
-              ret = gnutls_certificate_set_x509_crl_file
+              ret = fn_gnutls_certificate_set_x509_crl_file
                 (x509_cred,
                  SSDATA (crlfile),
                  file_format);
@@ -652,7 +866,7 @@ one trustfile (usually a CA bundle).  */)
                            SSDATA (keyfile));
               GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ",
                            SSDATA (certfile));
-              ret = gnutls_certificate_set_x509_key_file
+              ret = fn_gnutls_certificate_set_x509_key_file
                 (x509_cred,
                  SSDATA (certfile),
                  SSDATA (keyfile),
@@ -685,7 +899,7 @@ one trustfile (usually a CA bundle).  */)
 
   GNUTLS_LOG (1, max_log_level, "gnutls_init");
 
-  ret = gnutls_init (&state, GNUTLS_CLIENT);
+  ret = fn_gnutls_init (&state, GNUTLS_CLIENT);
 
   if (ret < GNUTLS_E_SUCCESS)
     return gnutls_make_error (ret);
@@ -708,9 +922,9 @@ one trustfile (usually a CA bundle).  */)
 
   GNUTLS_LOG (1, max_log_level, "setting the priority string");
 
-  ret = gnutls_priority_set_direct (state,
-                                   priority_string_ptr,
-                                   NULL);
+  ret = fn_gnutls_priority_set_direct (state,
+                                       priority_string_ptr,
+                                       NULL);
 
   if (ret < GNUTLS_E_SUCCESS)
     return gnutls_make_error (ret);
@@ -719,11 +933,11 @@ one trustfile (usually a CA bundle).  */)
 
   if (EQ (type, Qgnutls_x509pki))
     {
-      ret = gnutls_cred_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred);
+      ret = fn_gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred);
     }
   else if (EQ (type, Qgnutls_anon))
     {
-      ret = gnutls_cred_set (state, GNUTLS_CRD_ANON, anon_cred);
+      ret = fn_gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred);
     }
   else
     {
@@ -751,7 +965,7 @@ one trustfile (usually a CA bundle).  */)
      check of the certificate's hostname with
      gnutls_x509_crt_check_hostname() against :hostname.  */
 
-  ret = gnutls_certificate_verify_peers2 (state, &peer_verification);
+  ret = fn_gnutls_certificate_verify_peers2 (state, &peer_verification);
 
   if (ret < GNUTLS_E_SUCCESS)
     return gnutls_make_error (ret);
@@ -802,15 +1016,15 @@ one trustfile (usually a CA bundle).  */)
   /* Up to here the process is the same for X.509 certificates and
      OpenPGP keys.  From now on X.509 certificates are assumed.  This
      can be easily extended to work with openpgp keys as well.  */
-  if (gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
+  if (fn_gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
     {
-      ret = gnutls_x509_crt_init (&gnutls_verify_cert);
+      ret = fn_gnutls_x509_crt_init (&gnutls_verify_cert);
 
       if (ret < GNUTLS_E_SUCCESS)
         return gnutls_make_error (ret);
 
       gnutls_verify_cert_list =
-        gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
+        fn_gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
 
       if (NULL == gnutls_verify_cert_list)
         {
@@ -818,17 +1032,17 @@ one trustfile (usually a CA bundle).  */)
         }
 
       /* We only check the first certificate in the given chain.  */
-      ret = gnutls_x509_crt_import (gnutls_verify_cert,
-                                    &gnutls_verify_cert_list[0],
-                                    GNUTLS_X509_FMT_DER);
+      ret = fn_gnutls_x509_crt_import (gnutls_verify_cert,
+                                       &gnutls_verify_cert_list[0],
+                                       GNUTLS_X509_FMT_DER);
 
       if (ret < GNUTLS_E_SUCCESS)
         {
-          gnutls_x509_crt_deinit (gnutls_verify_cert);
+          fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
           return gnutls_make_error (ret);
         }
 
-      if (!gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname))
+      if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname))
         {
           if (NILP (verify_hostname_error))
             {
@@ -837,13 +1051,13 @@ one trustfile (usually a CA bundle).  */)
             }
           else
             {
-              gnutls_x509_crt_deinit (gnutls_verify_cert);
+              fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
               error ("The x509 certificate does not match \"%s\"",
                      c_hostname);
             }
         }
 
-      gnutls_x509_crt_deinit (gnutls_verify_cert);
+      fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
     }
 
   return gnutls_make_error (ret);
@@ -872,8 +1086,8 @@ This function may also return `gnutls-e-again', or
 
   state = XPROCESS (proc)->gnutls_state;
 
-  ret = gnutls_bye (state,
-                    NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
+  ret = fn_gnutls_bye (state,
+                       NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
 
   return gnutls_make_error (ret);
 }
@@ -883,6 +1097,9 @@ syms_of_gnutls (void)
 {
   gnutls_global_initialized = 0;
 
+  Qgnutls_dll = intern_c_string ("gnutls");
+  staticpro (&Qgnutls_dll);
+
   Qgnutls_log_level = intern_c_string ("gnutls-log-level");
   staticpro (&Qgnutls_log_level);
 
@@ -956,6 +1173,7 @@ syms_of_gnutls (void)
   defsubr (&Sgnutls_boot);
   defsubr (&Sgnutls_deinit);
   defsubr (&Sgnutls_bye);
+  defsubr (&Sgnutls_available_p);
 }
 
 #endif /* HAVE_GNUTLS */
index 6c2e4c6952312daeee17ea53c44ca3bfa49e60ee..afe6337fac2d54e4d44c786477b6312ecfe090d9 100644 (file)
@@ -42,6 +42,7 @@ typedef enum
   GNUTLS_STAGE_READY,
 } gnutls_initstage_t;
 
+#define GNUTLS_EMACS_ERROR_NOT_LOADED GNUTLS_E_APPLICATION_ERROR_MIN + 1
 #define GNUTLS_EMACS_ERROR_INVALID_TYPE GNUTLS_E_APPLICATION_ERROR_MIN
 
 #define GNUTLS_INITSTAGE(proc) (XPROCESS (proc)->gnutls_initstage)
@@ -52,13 +53,16 @@ typedef enum
 
 #define GNUTLS_LOG2(level, max, string, extra) if (level <= max) { gnutls_log_function2 (level, "(Emacs) " string, extra); }
 
-EMACS_INT
+extern EMACS_INT
 emacs_gnutls_write (int fildes, struct Lisp_Process *proc, const char *buf,
                     EMACS_INT nbyte);
-EMACS_INT
+extern EMACS_INT
 emacs_gnutls_read (int fildes, struct Lisp_Process *proc, char *buf,
                    EMACS_INT nbyte);
 
+extern int emacs_gnutls_record_check_pending (gnutls_session_t state);
+extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err);
+
 extern void syms_of_gnutls (void);
 
 #endif
index 6feeb75afd6f22b186b208187f22701269826620..2377b41735db6da3079cd01fa9a54dd97f1b5abf 100644 (file)
@@ -67,6 +67,7 @@ typedef struct x_bitmap_record Bitmap_Record;
 
 
 #ifdef HAVE_NTGUI
+#include "w32.h"
 #include "w32term.h"
 
 /* W32_TODO : Color tables on W32.  */
@@ -556,10 +557,6 @@ x_create_bitmap_mask (struct frame *f, int id)
 
 static struct image_type *image_types;
 
-/* Cache for delayed-loading image types.  */
-
-static Lisp_Object Vimage_type_cache;
-
 /* The symbol `xbm' which is used as the type symbol for XBM images.  */
 
 static Lisp_Object Qxbm;
@@ -589,7 +586,7 @@ static int x_build_heuristic_mask (struct frame *, struct image *,
                                    Lisp_Object);
 
 #define CACHE_IMAGE_TYPE(type, status) \
-  do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
+  do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0)
 
 #define ADD_IMAGE_TYPE(type) \
   do { Vimage_types = Fcons (type, Vimage_types); } while (0)
@@ -1900,34 +1897,6 @@ mark_image_cache (struct image_cache *c)
     if (!fn_##func) return 0;                                          \
   }
 
-/* Load a DLL implementing an image type.
-   The argument LIBRARIES is usually the variable
-   `dynamic-library-alist', which associates a symbol, identifying
-   an external DLL library, to a list of possible filenames.
-   The function returns NULL if no library could be loaded for
-   the given symbol, or if the library was previously loaded;
-   else the handle of the DLL.  */
-static HMODULE
-w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
-{
-  HMODULE library = NULL;
-
-  if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
-    {
-      Lisp_Object dlls = Fassq (type, libraries);
-
-      if (CONSP (dlls))
-        for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
-          {
-            CHECK_STRING_CAR (dlls);
-            if (library = LoadLibrary (SDATA (XCAR (dlls))))
-              break;
-          }
-    }
-
-  return library;
-}
-
 #endif /* HAVE_NTGUI */
 
 static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
@@ -5452,7 +5421,6 @@ init_png_functions (Lisp_Object libraries)
 {
   HMODULE library;
 
-  /* Try loading libpng under probable names.  */
   if (!(library = w32_delayed_load (libraries, Qpng)))
     return 0;
 
@@ -8634,7 +8602,7 @@ of `dynamic-library-alist', which see).  */)
   Lisp_Object tested;
 
   /* Don't try to reload the library.  */
-  tested = Fassq (type, Vimage_type_cache);
+  tested = Fassq (type, Vlibrary_cache);
   if (CONSP (tested))
     return XCDR (tested);
 
@@ -8714,9 +8682,6 @@ as a ratio to the frame height and width.  If the value is
 non-numeric, there is no explicit limit on the size of images.  */);
   Vmax_image_size = make_float (MAX_IMAGE_SIZE);
 
-  Vimage_type_cache = Qnil;
-  staticpro (&Vimage_type_cache);
-
   Qpbm = intern_c_string ("pbm");
   staticpro (&Qpbm);
   ADD_IMAGE_TYPE (Qpbm);
index 537030783077402e58050108ae52f74db3f94d15..454f7d8a9aa7db326e781dca4c2607f3bf645757 100644 (file)
@@ -33,6 +33,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <unistd.h>
 #include <fcntl.h>
 
+#include "lisp.h"
+
 /* Only MS-DOS does not define `subprocesses'.  */
 #ifdef subprocesses
 
@@ -77,7 +79,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #endif /* subprocesses */
 
-#include "lisp.h"
 #include "systime.h"
 #include "systty.h"
 
@@ -4537,10 +4538,10 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              some data in the TCP buffers so that select works, but
              with custom pull/push functions we need to check if some
              data is available in the buffers manually.  */
-          if (nfds == 0 && 
+          if (nfds == 0 &&
               wait_proc && wait_proc->gnutls_p /* Check for valid process.  */
               /* Do we have pending data?  */
-              && gnutls_record_check_pending (wait_proc->gnutls_state) > 0)
+              && emacs_gnutls_record_check_pending (wait_proc->gnutls_state) > 0)
           {
               nfds = 1;
               /* Set to Available.  */
index 230ccc8de1017908a1d8d9ab8d25a709995d9c4a..d81fdf3305d0c103f5edca67d81a4ae3cbe87d7e 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -150,6 +150,8 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
   (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
 
+Lisp_Object QCloaded_from;
+
 void globals_of_w32 (void);
 static DWORD get_rid (PSID);
 
@@ -5712,6 +5714,54 @@ sys_localtime (const time_t *t)
   return localtime (t);
 }
 
+
+\f
+/* Delayed loading of libraries.  */
+
+Lisp_Object Vlibrary_cache;
+
+/* The argument LIBRARIES is an alist that associates a symbol
+   LIBRARY_ID, identifying an external DLL library known to Emacs, to
+   a list of filenames under which the library is usually found.  In
+   most cases, the argument passed as LIBRARIES is the variable
+   `dynamic-library-alist', which is initialized to a list of common
+   library names.  If the function loads the library successfully, it
+   returns the handle of the DLL, and records the filename in the
+   property :loaded-from of LIBRARY_ID; it returns NULL if the library
+   could not be found, or when it was already loaded (because the
+   handle is not recorded anywhere, and so is lost after use).  It
+   would be trivial to save the handle too in :loaded-from, but
+   currently there's no use case for it.  */
+HMODULE
+w32_delayed_load (Lisp_Object libraries, Lisp_Object library_id)
+{
+  HMODULE library_dll = NULL;
+
+  CHECK_SYMBOL (library_id);
+
+  if (CONSP (libraries) && NILP (Fassq (library_id, Vlibrary_cache)))
+    {
+      Lisp_Object found = Qnil;
+      Lisp_Object dlls = Fassq (library_id, libraries);
+
+      if (CONSP (dlls))
+        for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
+          {
+            CHECK_STRING_CAR (dlls);
+            if (library_dll = LoadLibrary (SDATA (XCAR (dlls))))
+              {
+                found = XCAR (dlls);
+                break;
+              }
+          }
+
+      Fput (library_id, QCloaded_from, found);
+    }
+
+  return library_dll;
+}
+
+\f
 static void
 check_windows_init_file (void)
 {
@@ -5910,6 +5960,12 @@ globals_of_w32 (void)
   get_process_times_fn = (GetProcessTimes_Proc)
     GetProcAddress (kernel32, "GetProcessTimes");
 
+  QCloaded_from = intern_c_string (":loaded-from");
+  staticpro (&QCloaded_from);
+
+  Vlibrary_cache = Qnil;
+  staticpro (&Vlibrary_cache);
+
   g_b_init_is_windows_9x = 0;
   g_b_init_open_process_token = 0;
   g_b_init_get_token_information = 0;
@@ -6178,7 +6234,7 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
             err = errno; /* Other errors are just passed on.  */
         }
 
-      gnutls_transport_set_errno (process->gnutls_state, err);
+      emacs_gnutls_transport_set_errno (process->gnutls_state, err);
 
       return -1;
     }
@@ -6197,8 +6253,8 @@ emacs_gnutls_push (gnutls_transport_ptr_t p, const void* buf, size_t sz)
 
   /* Negative bytes written means we got an error in errno.
      Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN.  */
-  gnutls_transport_set_errno (process->gnutls_state,
-                              errno == EWOULDBLOCK ? EAGAIN : errno);
+  emacs_gnutls_transport_set_errno (process->gnutls_state,
+                                    errno == EWOULDBLOCK ? EAGAIN : errno);
 
   return -1;
 }
index 4086c4190e17b7594bd1b36f166fe17adb2c8a19..f1915125c906f2d2893b1580c28ade80d60b0920 100644 (file)
--- a/src/w32.h
+++ b/src/w32.h
@@ -143,6 +143,9 @@ extern void syms_of_fontset (void);
 extern int _sys_read_ahead (int fd);
 extern int _sys_wait_accept (int fd);
 
+extern Lisp_Object Vlibrary_cache, QCloaded_from;
+extern HMODULE w32_delayed_load (Lisp_Object, Lisp_Object);
+
 #ifdef HAVE_GNUTLS
 #include <gnutls/gnutls.h>