1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Steve Holme, <steve_holme@hotmail.com>. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25#include "curl_setup.h" 26 27#if defined(_WIN32) 28 29#include <curl/curl.h> 30#include "system_win32.h" 31#include "version_win32.h" 32#include "curl_sspi.h" 33#include "warnless.h" 34 35/* The last #include files should be: */ 36#include "curl_memory.h" 37#include "memdebug.h" 38 39LARGE_INTEGER Curl_freq; 40bool Curl_isVistaOrGreater; 41bool Curl_isWindows8OrGreater; 42 43/* Handle of iphlpapp.dll */ 44static HMODULE s_hIpHlpApiDll = NULL; 45 46/* Function pointers */ 47IF_NAMETOINDEX_FN Curl_if_nametoindex = NULL; 48FREEADDRINFOEXW_FN Curl_FreeAddrInfoExW = NULL; 49GETADDRINFOEXCANCEL_FN Curl_GetAddrInfoExCancel = NULL; 50GETADDRINFOEXW_FN Curl_GetAddrInfoExW = NULL; 51 52/* Curl_win32_init() performs win32 global initialization */ 53CURLcode Curl_win32_init(long flags) 54{ 55#ifdef USE_WINSOCK 56 HMODULE ws2_32Dll; 57#endif 58 /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which 59 is just for Winsock at the moment. Any required win32 initialization 60 should take place after this block. */ 61 if(flags & CURL_GLOBAL_WIN32) { 62#ifdef USE_WINSOCK 63 WORD wVersionRequested; 64 WSADATA wsaData; 65 int res; 66 67 wVersionRequested = MAKEWORD(2, 2); 68 res = WSAStartup(wVersionRequested, &wsaData); 69 70 if(res) 71 /* Tell the user that we couldn't find a usable */ 72 /* winsock.dll. */ 73 return CURLE_FAILED_INIT; 74 75 /* Confirm that the Windows Sockets DLL supports what we need.*/ 76 /* Note that if the DLL supports versions greater */ 77 /* than wVersionRequested, it will still return */ 78 /* wVersionRequested in wVersion. wHighVersion contains the */ 79 /* highest supported version. */ 80 81 if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || 82 HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { 83 /* Tell the user that we couldn't find a usable */ 84 85 /* winsock.dll. */ 86 WSACleanup(); 87 return CURLE_FAILED_INIT; 88 } 89 /* The Windows Sockets DLL is acceptable. Proceed. */ 90#elif defined(USE_LWIPSOCK) 91 lwip_init(); 92#endif 93 } /* CURL_GLOBAL_WIN32 */ 94 95#ifdef USE_WINDOWS_SSPI 96 { 97 CURLcode result = Curl_sspi_global_init(); 98 if(result) 99 return result; 100 } 101#endif 102 103 s_hIpHlpApiDll = Curl_load_library(TEXT("iphlpapi.dll")); 104 if(s_hIpHlpApiDll) { 105 /* Get the address of the if_nametoindex function */ 106 IF_NAMETOINDEX_FN pIfNameToIndex = 107 CURLX_FUNCTION_CAST(IF_NAMETOINDEX_FN, 108 (GetProcAddress(s_hIpHlpApiDll, "if_nametoindex"))); 109 110 if(pIfNameToIndex) 111 Curl_if_nametoindex = pIfNameToIndex; 112 } 113 114#ifdef USE_WINSOCK 115 ws2_32Dll = GetModuleHandleA("ws2_32"); 116 if(ws2_32Dll) { 117 Curl_FreeAddrInfoExW = CURLX_FUNCTION_CAST(FREEADDRINFOEXW_FN, 118 GetProcAddress(ws2_32Dll, "FreeAddrInfoExW")); 119 Curl_GetAddrInfoExCancel = CURLX_FUNCTION_CAST(GETADDRINFOEXCANCEL_FN, 120 GetProcAddress(ws2_32Dll, "GetAddrInfoExCancel")); 121 Curl_GetAddrInfoExW = CURLX_FUNCTION_CAST(GETADDRINFOEXW_FN, 122 GetProcAddress(ws2_32Dll, "GetAddrInfoExW")); 123 } 124#endif 125 126 /* curlx_verify_windows_version must be called during init at least once 127 because it has its own initialization routine. */ 128 if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT, 129 VERSION_GREATER_THAN_EQUAL)) { 130 Curl_isVistaOrGreater = TRUE; 131 } 132 else 133 Curl_isVistaOrGreater = FALSE; 134 135 if(curlx_verify_windows_version(6, 2, 0, PLATFORM_WINNT, 136 VERSION_GREATER_THAN_EQUAL)) { 137 Curl_isWindows8OrGreater = TRUE; 138 } 139 else 140 Curl_isWindows8OrGreater = FALSE; 141 142 QueryPerformanceFrequency(&Curl_freq); 143 return CURLE_OK; 144} 145 146/* Curl_win32_cleanup() is the opposite of Curl_win32_init() */ 147void Curl_win32_cleanup(long init_flags) 148{ 149 Curl_FreeAddrInfoExW = NULL; 150 Curl_GetAddrInfoExCancel = NULL; 151 Curl_GetAddrInfoExW = NULL; 152 if(s_hIpHlpApiDll) { 153 FreeLibrary(s_hIpHlpApiDll); 154 s_hIpHlpApiDll = NULL; 155 Curl_if_nametoindex = NULL; 156 } 157 158#ifdef USE_WINDOWS_SSPI 159 Curl_sspi_global_cleanup(); 160#endif 161 162 if(init_flags & CURL_GLOBAL_WIN32) { 163#ifdef USE_WINSOCK 164 WSACleanup(); 165#endif 166 } 167} 168 169#if !defined(LOAD_WITH_ALTERED_SEARCH_PATH) 170#define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008 171#endif 172 173#if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32) 174#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 175#endif 176 177/* We use our own typedef here since some headers might lack these */ 178typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); 179 180/* See function definitions in winbase.h */ 181#ifdef UNICODE 182# ifdef _WIN32_WCE 183# define LOADLIBARYEX L"LoadLibraryExW" 184# else 185# define LOADLIBARYEX "LoadLibraryExW" 186# endif 187#else 188# define LOADLIBARYEX "LoadLibraryExA" 189#endif 190 191/* 192 * Curl_load_library() 193 * 194 * This is used to dynamically load DLLs using the most secure method available 195 * for the version of Windows that we are running on. 196 * 197 * Parameters: 198 * 199 * filename [in] - The filename or full path of the DLL to load. If only the 200 * filename is passed then the DLL will be loaded from the 201 * Windows system directory. 202 * 203 * Returns the handle of the module on success; otherwise NULL. 204 */ 205HMODULE Curl_load_library(LPCTSTR filename) 206{ 207#ifndef CURL_WINDOWS_APP 208 HMODULE hModule = NULL; 209 LOADLIBRARYEX_FN pLoadLibraryEx = NULL; 210 211 /* Get a handle to kernel32 so we can access it's functions at runtime */ 212 HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32")); 213 if(!hKernel32) 214 return NULL; 215 216 /* Attempt to find LoadLibraryEx() which is only available on Windows 2000 217 and above */ 218 pLoadLibraryEx = 219 CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN, 220 (GetProcAddress(hKernel32, LOADLIBARYEX))); 221 222 /* Detect if there's already a path in the filename and load the library if 223 there is. Note: Both back slashes and forward slashes have been supported 224 since the earlier days of DOS at an API level although they are not 225 supported by command prompt */ 226 if(_tcspbrk(filename, TEXT("\\/"))) { 227 /** !checksrc! disable BANNEDFUNC 1 **/ 228 hModule = pLoadLibraryEx ? 229 pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : 230 LoadLibrary(filename); 231 } 232 /* Detect if KB2533623 is installed, as LOAD_LIBRARY_SEARCH_SYSTEM32 is only 233 supported on Windows Vista, Windows Server 2008, Windows 7 and Windows 234 Server 2008 R2 with this patch or natively on Windows 8 and above */ 235 else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) { 236 /* Load the DLL from the Windows system directory */ 237 hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); 238 } 239 else { 240 /* Attempt to get the Windows system path */ 241 UINT systemdirlen = GetSystemDirectory(NULL, 0); 242 if(systemdirlen) { 243 /* Allocate space for the full DLL path (Room for the null terminator 244 is included in systemdirlen) */ 245 size_t filenamelen = _tcslen(filename); 246 TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen)); 247 if(path && GetSystemDirectory(path, systemdirlen)) { 248 /* Calculate the full DLL path */ 249 _tcscpy(path + _tcslen(path), TEXT("\\")); 250 _tcscpy(path + _tcslen(path), filename); 251 252 /* Load the DLL from the Windows system directory */ 253 /** !checksrc! disable BANNEDFUNC 1 **/ 254 hModule = pLoadLibraryEx ? 255 pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : 256 LoadLibrary(path); 257 258 } 259 free(path); 260 } 261 } 262 return hModule; 263#else 264 /* the Universal Windows Platform (UWP) can't do this */ 265 (void)filename; 266 return NULL; 267#endif 268} 269 270#endif /* _WIN32 */ 271