These macros are soooooooo ugly!
why not do this simply like other examples in OpenVPN code, if I
recall correctly in CryptoAPI module.

On Wed, Aug 17, 2011 at 4:42 PM, Heiko Hund <heiko.h...@sophos.com> wrote:
> MinGW is missing support for winhttp.dll which will be used for automatic
> proxy server detection in Windows. Until it becomes available the workaround
> performed is to provide wrapper functions and dynamically map the missing
> library into the address space, get the function pointer for the actual API
> and call it with the arguments provided.
>
> To keep things managable and short in the source code two preprocessor macros
> are defined that do most of the work.
>
> Signed-off-by: Heiko Hund <heiko.h...@sophos.com>
> ---
>  configure.ac |   30 ++++++++++++++++
>  win32.c      |  108 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  win32.h      |   61 ++++++++++++++++++++++++++++++++
>  3 files changed, 199 insertions(+), 0 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index a3789d9..42d46cb 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -665,6 +665,36 @@ if test "${WIN32}" = "yes"; then
>  fi
>
>  dnl
> +dnl Check if MinGW knows about WinHTTP API
> +dnl
> +if test "${WIN32}" = "yes"; then
> +   AC_MSG_CHECKING([if MinGW knows about WinHTTP])
> +   AC_TRY_LINK([
> +       #include <windows.h>
> +       #include <winhttp.h>
> +     ], [
> +       LPWSTR *url;
> +       HINTERNET session;
> +       WINHTTP_PROXY_INFO proxy_info;
> +       WINHTTP_AUTOPROXY_OPTIONS proxy_options;
> +       WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_proxy_info;
> +
> +       WinHttpGetDefaultProxyConfiguration (&proxy_info);
> +       WinHttpGetIEProxyConfigForCurrentUser (&ie_proxy_info);
> +       WinHttpDetectAutoProxyConfigUrl (WINHTTP_AUTO_DETECT_TYPE_DHCP | 
> WINHTTP_AUTO_DETECT_TYPE_DNS_A, url);
> +       session = WinHttpOpen (NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, 
> WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
> +       WinHttpGetProxyForUrl (session, L"http://openvpn.net";, 
> &proxy_options, &proxy_info);
> +       WinHttpCloseHandle (session);
> +     ], [
> +       AC_MSG_RESULT([yes])
> +     ], [
> +       AC_MSG_RESULT([no.])
> +       AC_MSG_NOTICE([Enabling WinHTTP compatibility layer.])
> +       AC_DEFINE(USE_WINHTTP_COMPAT, 1, [Use the WinHTTP compatibility 
> layer])
> +     ])
> +fi
> +
> +dnl
>  dnl check for LZO library
>  dnl
>
> diff --git a/win32.c b/win32.c
> index cf6cc2d..15743a8 100644
> --- a/win32.c
> +++ b/win32.c
> @@ -1128,4 +1128,112 @@ win_get_tempdir()
>   }
>   return tmpdir;
>  }
> +
> +
> +#ifdef USE_WINHTTP_COMPAT
> +
> +/*
> + * MinGW is missing support for winhttp.dll which is used for automatic
> + * proxy server detection. Until it becomes available the workaround is
> + * to dynamically map the library into the address space and get the
> + * function pointers for the APIs that are used. The two macros below
> + * do just that.
> + *
> + * PROVIDE_WIN32_LIBRARY provides means to access API functions.
> + *     Arguments: LIB - name of the DLL to load
> + *
> + * DEFINE_WIN32_WRAPPER defines a wrapper function around the
> + * original API provoded by the library. The original API can
> + * be accessed within the wrapper as <LIB>_<FUNC> (see Arguments).
> + *     Arguments: LIB   name of the DLL the function is exported in
> + *                ERR   value to return in case something goes wrong
> + *                RET   API function's return value type
> + *                FUNC  exported name of the API function
> + *                ARGS  declaration of the API function arguments
> + *                BODY  the wrapper function's body
> + */
> +
> +#define PROVIDE_WIN32_LIBRARY(LIB)                                    \
> +  static HMODULE get_ ## LIB ## _library ()                           \
> +  {                                                                   \
> +    static HMODULE lib = NULL;                                        \
> +                                                                      \
> +    if (lib == NULL)                                                  \
> +      {                                                               \
> +       char name[MAX_PATH];                                          \
> +       UINT len = GetSystemDirectory (name, sizeof (name));          \
> +       if (len == 0)                                                 \
> +         return NULL;                                                \
> +                                                                      \
> +       strncpy (name + len, "\\" #LIB ".dll", sizeof (name) - len);  \
> +       name[sizeof (name) - 1] = '\0';                               \
> +                                                                      \
> +       lib = LoadLibrary (name);                                     \
> +      }                                                               \
> +                                                                      \
> +    return lib;                                                       \
> +  }
> +
> +#define DEFINE_WIN32_WRAPPER(LIB, ERR, RET, FUNC, ARGS, BODY)  \
> +  RET FUNC ARGS                                                \
> +  {                                                            \
> +    typedef RET (WINAPI *(FUNC ## _fn)) ARGS;                  \
> +    static FUNC ## _fn  LIB ## _ ## FUNC = NULL;               \
> +                                                               \
> +    if ((LIB ## _ ## FUNC) == NULL)                            \
> +      {                                                        \
> +       union {                                                \
> +         FUNC ## _fn *type;                                   \
> +         FARPROC *ptr;                                        \
> +       } u = { .type = &(LIB ## _ ## FUNC) };                 \
> +                                                               \
> +       HMODULE lib = get_ ## LIB ## _library ();              \
> +       if (lib == NULL)                                       \
> +         return (ERR);                                        \
> +                                                               \
> +       *(u.ptr) = GetProcAddress (lib, (#FUNC));              \
> +       if ((LIB ## _ ## FUNC) == NULL)                        \
> +         return (ERR);                                        \
> +      }                                                        \
> +                                                               \
> +    BODY                                                       \
> +  }
> +
> +
> +PROVIDE_WIN32_LIBRARY (winhttp)
> +
> +DEFINE_WIN32_WRAPPER (winhttp, NULL, HINTERNET,
> +WinHttpOpen, (LPCWSTR user_agent, DWORD access_type, LPCWSTR proxy, LPCWSTR 
> bypass, DWORD flags),
> +  return winhttp_WinHttpOpen (user_agent, access_type, proxy, bypass, flags);
> +)
> +
> +DEFINE_WIN32_WRAPPER (winhttp, FALSE, BOOL,
> +WinHttpCloseHandle, (HINTERNET session),
> +  return winhttp_WinHttpCloseHandle (session);
> +)
> +
> +DEFINE_WIN32_WRAPPER (winhttp, FALSE, BOOL,
> +WinHttpGetDefaultProxyConfiguration, (WINHTTP_PROXY_INFO *proxy_info),
> +  return winhttp_WinHttpGetDefaultProxyConfiguration (proxy_info);
> +)
> +
> +DEFINE_WIN32_WRAPPER (winhttp, FALSE, BOOL,
> +WinHttpGetIEProxyConfigForCurrentUser, (WINHTTP_CURRENT_USER_IE_PROXY_CONFIG 
> *proxy_config),
> +  return winhttp_WinHttpGetIEProxyConfigForCurrentUser(proxy_config);
> +)
> +
> +DEFINE_WIN32_WRAPPER (winhttp, FALSE, BOOL,
> +WinHttpDetectAutoProxyConfigUrl, (DWORD flags, LPWSTR *url),
> +  return winhttp_WinHttpDetectAutoProxyConfigUrl (flags, url);
> +)
> +
> +DEFINE_WIN32_WRAPPER (winhttp, FALSE, BOOL,
> +WinHttpGetProxyForUrl, (HINTERNET session, LPCWSTR url,
> +                       WINHTTP_AUTOPROXY_OPTIONS *options,
> +                       WINHTTP_PROXY_INFO *proxy_info),
> +  return winhttp_WinHttpGetProxyForUrl (session, url, options, proxy_info);
> +)
> +
> +#endif /* USE_WINHTTP_COMPAT */
> +
>  #endif
> diff --git a/win32.h b/win32.h
> index 87d8ecc..2ff4b8c 100644
> --- a/win32.h
> +++ b/win32.h
> @@ -288,5 +288,66 @@ int inet_pton(int af, const char *src, void *st);
>  /* Find temporary directory */
>  const char *win_get_tempdir();
>
> +/*
> + * If MinGW does not know about the WinHTTP C API functions and
> + * constants that are used for automatic proxy server detection
> + * they are declared here. For detailed information see:
> + * http://msdn.microsoft.com/en-us/library/aa384252%28v=VS.85%29.aspx
> + */
> +#ifdef USE_WINHTTP_COMPAT
> +
> +#include <windows.h>
> +#include <wininet.h>
> +
> +/* WINHTTP_PROXY_INFO dwAccessType constants */
> +/* and WinHttpOpen() access_type             */
> +#define WINHTTP_ACCESS_TYPE_NO_PROXY     1
> +#define WINHTTP_ACCESS_TYPE_NAMED_PROXY  3
> +
> +/* WinHttpDetectAutoProxyConfigUrl() flags */
> +#define WINHTTP_AUTO_DETECT_TYPE_DHCP   1
> +#define WINHTTP_AUTO_DETECT_TYPE_DNS_A  2
> +
> +/* WINHTTP_AUTOPROXY_OPTIONS dwFlags */
> +#define WINHTTP_AUTOPROXY_CONFIG_URL   2
> +
> +/* WinHttpOpen() proxy and bypass values */
> +#define WINHTTP_NO_PROXY_NAME    0
> +#define WINHTTP_NO_PROXY_BYPASS  0
> +
> +typedef struct {
> +  DWORD  dwAccessType;
> +  LPWSTR lpszProxy;
> +  LPWSTR lpszProxyBypass;
> +} WINHTTP_PROXY_INFO;
> +
> +typedef struct {
> +  BOOL   fAutoDetect;
> +  LPWSTR lpszAutoConfigUrl;
> +  LPWSTR lpszProxy;
> +  LPWSTR lpszProxyBypass;
> +} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
> +
> +typedef struct {
> +  DWORD   dwFlags;
> +  DWORD   dwAutoDetectFlags;
> +  LPCWSTR lpszAutoConfigUrl;
> +  LPVOID  lpvReserved;
> +  DWORD   dwReserved;
> +  BOOL    fAutoLogonIfChallenged;
> +} WINHTTP_AUTOPROXY_OPTIONS;
> +
> +HINTERNET WinHttpOpen (LPCWSTR user_agent, DWORD access_type,
> +                      LPCWSTR proxy, LPCWSTR bypass, DWORD flags);
> +BOOL WinHttpCloseHandle (HINTERNET session);
> +BOOL WinHttpGetDefaultProxyConfiguration (WINHTTP_PROXY_INFO *proxy_info);
> +BOOL WinHttpGetIEProxyConfigForCurrentUser 
> (WINHTTP_CURRENT_USER_IE_PROXY_CONFIG *proxy_config);
> +BOOL WinHttpDetectAutoProxyConfigUrl (DWORD flags, LPWSTR *url);
> +BOOL WinHttpGetProxyForUrl (HINTERNET session, LPCWSTR url,
> +                           WINHTTP_AUTOPROXY_OPTIONS *options,
> +                           WINHTTP_PROXY_INFO *proxy_info);
> +
> +#endif /* USE_WINHTTP_COMPAT */
> +
>  #endif
>  #endif
> --
> 1.7.5.4
>
>
> ------------------------------------------------------------------------------
> Get a FREE DOWNLOAD! and learn more about uberSVN rich system,
> user administration capabilities and model configuration. Take
> the hassle out of deploying and managing Subversion and the
> tools developers use with it. http://p.sf.net/sfu/wandisco-d2d-2
> _______________________________________________
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel
>

Reply via email to