| |
| /* Copyright 1998 by the Massachusetts Institute of Technology. |
| * Copyright (C) 2004-2009 by Daniel Stenberg |
| * |
| * Permission to use, copy, modify, and distribute this |
| * software and its documentation for any purpose and without |
| * fee is hereby granted, provided that the above copyright |
| * notice appear in all copies and that both that copyright |
| * notice and this permission notice appear in supporting |
| * documentation, and that the name of M.I.T. not be used in |
| * advertising or publicity pertaining to distribution of the |
| * software without specific, written prior permission. |
| * M.I.T. makes no representations about the suitability of |
| * this software for any purpose. It is provided "as is" |
| * without express or implied warranty. |
| */ |
| |
| #include "ares_setup.h" |
| |
| #include "ares.h" |
| #include "ares_library_init.h" |
| #include "ares_private.h" |
| |
| /* library-private global and unique instance vars */ |
| |
| #ifdef USE_WINSOCK |
| fpGetNetworkParams_t ares_fpGetNetworkParams = ZERO_NULL; |
| fpSystemFunction036_t ares_fpSystemFunction036 = ZERO_NULL; |
| fpGetAdaptersAddresses_t ares_fpGetAdaptersAddresses = ZERO_NULL; |
| fpGetBestRoute2_t ares_fpGetBestRoute2 = ZERO_NULL; |
| #endif |
| |
| /* library-private global vars with source visibility restricted to this file */ |
| |
| static unsigned int ares_initialized; |
| static int ares_init_flags; |
| |
| /* library-private global vars with visibility across the whole library */ |
| void *(*ares_malloc)(size_t size) = malloc; |
| void *(*ares_realloc)(void *ptr, size_t size) = realloc; |
| void (*ares_free)(void *ptr) = free; |
| |
| #ifdef USE_WINSOCK |
| static HMODULE hnd_iphlpapi; |
| static HMODULE hnd_advapi32; |
| #endif |
| |
| |
| static int ares_win32_init(void) |
| { |
| #ifdef USE_WINSOCK |
| |
| hnd_iphlpapi = 0; |
| hnd_iphlpapi = LoadLibraryW(L"iphlpapi.dll"); |
| if (!hnd_iphlpapi) |
| return ARES_ELOADIPHLPAPI; |
| |
| ares_fpGetNetworkParams = (fpGetNetworkParams_t) |
| GetProcAddress(hnd_iphlpapi, "GetNetworkParams"); |
| if (!ares_fpGetNetworkParams) |
| { |
| FreeLibrary(hnd_iphlpapi); |
| return ARES_EADDRGETNETWORKPARAMS; |
| } |
| |
| ares_fpGetAdaptersAddresses = (fpGetAdaptersAddresses_t) |
| GetProcAddress(hnd_iphlpapi, "GetAdaptersAddresses"); |
| if (!ares_fpGetAdaptersAddresses) |
| { |
| /* This can happen on clients before WinXP, I don't |
| think it should be an error, unless we don't want to |
| support Windows 2000 anymore */ |
| } |
| |
| ares_fpGetBestRoute2 = (fpGetBestRoute2_t) |
| GetProcAddress(hnd_iphlpapi, "GetBestRoute2"); |
| if (!ares_fpGetBestRoute2) |
| { |
| /* This can happen on clients before Vista, I don't |
| think it should be an error, unless we don't want to |
| support Windows XP anymore */ |
| } |
| |
| /* |
| * When advapi32.dll is unavailable or advapi32.dll has no SystemFunction036, |
| * also known as RtlGenRandom, which is the case for Windows versions prior |
| * to WinXP then c-ares uses portable rand() function. Then don't error here. |
| */ |
| |
| hnd_advapi32 = 0; |
| hnd_advapi32 = LoadLibraryW(L"advapi32.dll"); |
| if (hnd_advapi32) |
| { |
| ares_fpSystemFunction036 = (fpSystemFunction036_t) |
| GetProcAddress(hnd_advapi32, "SystemFunction036"); |
| } |
| |
| #endif |
| return ARES_SUCCESS; |
| } |
| |
| |
| static void ares_win32_cleanup(void) |
| { |
| #ifdef USE_WINSOCK |
| if (hnd_advapi32) |
| FreeLibrary(hnd_advapi32); |
| if (hnd_iphlpapi) |
| FreeLibrary(hnd_iphlpapi); |
| #endif |
| } |
| |
| |
| int ares_library_init(int flags) |
| { |
| int res; |
| |
| if (ares_initialized) |
| { |
| ares_initialized++; |
| return ARES_SUCCESS; |
| } |
| ares_initialized++; |
| |
| if (flags & ARES_LIB_INIT_WIN32) |
| { |
| res = ares_win32_init(); |
| if (res != ARES_SUCCESS) |
| return res; /* LCOV_EXCL_LINE: can't test Win32 init failure */ |
| } |
| |
| ares_init_flags = flags; |
| |
| return ARES_SUCCESS; |
| } |
| |
| int ares_library_init_mem(int flags, |
| void *(*amalloc)(size_t size), |
| void (*afree)(void *ptr), |
| void *(*arealloc)(void *ptr, size_t size)) |
| { |
| if (amalloc) |
| ares_malloc = amalloc; |
| if (arealloc) |
| ares_realloc = arealloc; |
| if (afree) |
| ares_free = afree; |
| return ares_library_init(flags); |
| } |
| |
| |
| void ares_library_cleanup(void) |
| { |
| if (!ares_initialized) |
| return; |
| ares_initialized--; |
| if (ares_initialized) |
| return; |
| |
| if (ares_init_flags & ARES_LIB_INIT_WIN32) |
| ares_win32_cleanup(); |
| |
| ares_init_flags = ARES_LIB_INIT_NONE; |
| ares_malloc = malloc; |
| ares_realloc = realloc; |
| ares_free = free; |
| } |
| |
| |
| int ares_library_initialized(void) |
| { |
| #ifdef USE_WINSOCK |
| if (!ares_initialized) |
| return ARES_ENOTINITIALIZED; |
| #endif |
| return ARES_SUCCESS; |
| } |