system_win32.c (8007B)
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 #ifdef _WIN32 28 29 #include <curl/curl.h> 30 #include "system_win32.h" 31 #include "curlx/version_win32.h" 32 #include "curl_sspi.h" 33 #include "curlx/warnless.h" 34 35 /* The last #include files should be: */ 36 #include "curl_memory.h" 37 #include "memdebug.h" 38 39 #ifndef HAVE_IF_NAMETOINDEX 40 /* Handle of iphlpapp.dll */ 41 static HMODULE s_hIpHlpApiDll = NULL; 42 43 /* Pointer to the if_nametoindex function */ 44 IF_NAMETOINDEX_FN Curl_if_nametoindex = NULL; 45 46 /* This is used to dynamically load DLLs */ 47 static HMODULE curl_load_library(LPCTSTR filename); 48 #endif 49 50 /* Curl_win32_init() performs Win32 global initialization */ 51 CURLcode Curl_win32_init(long flags) 52 { 53 /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which 54 is just for Winsock at the moment. Any required Win32 initialization 55 should take place after this block. */ 56 if(flags & CURL_GLOBAL_WIN32) { 57 #ifdef USE_WINSOCK 58 WORD wVersionRequested; 59 WSADATA wsaData; 60 int res; 61 62 wVersionRequested = MAKEWORD(2, 2); 63 res = WSAStartup(wVersionRequested, &wsaData); 64 65 if(res) 66 /* Tell the user that we could not find a usable */ 67 /* winsock.dll. */ 68 return CURLE_FAILED_INIT; 69 70 /* Confirm that the Windows Sockets DLL supports what we need.*/ 71 /* Note that if the DLL supports versions greater */ 72 /* than wVersionRequested, it will still return */ 73 /* wVersionRequested in wVersion. wHighVersion contains the */ 74 /* highest supported version. */ 75 76 if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || 77 HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { 78 /* Tell the user that we could not find a usable */ 79 80 /* winsock.dll. */ 81 WSACleanup(); 82 return CURLE_FAILED_INIT; 83 } 84 /* The Windows Sockets DLL is acceptable. Proceed. */ 85 #elif defined(USE_LWIPSOCK) 86 lwip_init(); 87 #endif 88 } /* CURL_GLOBAL_WIN32 */ 89 90 #ifdef USE_WINDOWS_SSPI 91 { 92 CURLcode result = Curl_sspi_global_init(); 93 if(result) 94 return result; 95 } 96 #endif 97 98 #ifndef HAVE_IF_NAMETOINDEX 99 s_hIpHlpApiDll = curl_load_library(TEXT("iphlpapi.dll")); 100 if(s_hIpHlpApiDll) { 101 /* Get the address of the if_nametoindex function */ 102 #ifdef UNDER_CE 103 #define CURL_TEXT(n) TEXT(n) 104 #else 105 #define CURL_TEXT(n) (n) 106 #endif 107 IF_NAMETOINDEX_FN pIfNameToIndex = 108 CURLX_FUNCTION_CAST(IF_NAMETOINDEX_FN, 109 (GetProcAddress(s_hIpHlpApiDll, 110 CURL_TEXT("if_nametoindex")))); 111 112 if(pIfNameToIndex) 113 Curl_if_nametoindex = pIfNameToIndex; 114 } 115 #endif 116 117 /* curlx_verify_windows_version must be called during init at least once 118 because it has its own initialization routine. */ 119 if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT, 120 VERSION_GREATER_THAN_EQUAL)) { 121 Curl_isVistaOrGreater = TRUE; 122 } 123 else 124 Curl_isVistaOrGreater = FALSE; 125 126 QueryPerformanceFrequency(&Curl_freq); 127 return CURLE_OK; 128 } 129 130 /* Curl_win32_cleanup() is the opposite of Curl_win32_init() */ 131 void Curl_win32_cleanup(long init_flags) 132 { 133 #ifndef HAVE_IF_NAMETOINDEX 134 if(s_hIpHlpApiDll) { 135 FreeLibrary(s_hIpHlpApiDll); 136 s_hIpHlpApiDll = NULL; 137 Curl_if_nametoindex = NULL; 138 } 139 #endif 140 141 #ifdef USE_WINDOWS_SSPI 142 Curl_sspi_global_cleanup(); 143 #endif 144 145 if(init_flags & CURL_GLOBAL_WIN32) { 146 #ifdef USE_WINSOCK 147 WSACleanup(); 148 #endif 149 } 150 } 151 152 #ifndef HAVE_IF_NAMETOINDEX 153 154 #ifndef LOAD_WITH_ALTERED_SEARCH_PATH 155 #define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008 156 #endif 157 158 #ifndef LOAD_LIBRARY_SEARCH_SYSTEM32 159 #define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 160 #endif 161 162 /* We use our own typedef here since some headers might lack these */ 163 typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); 164 165 /* See function definitions in winbase.h */ 166 #ifdef UNICODE 167 # ifdef UNDER_CE 168 # define LOADLIBARYEX L"LoadLibraryExW" 169 # else 170 # define LOADLIBARYEX "LoadLibraryExW" 171 # endif 172 #else 173 # define LOADLIBARYEX "LoadLibraryExA" 174 #endif 175 176 /* 177 * curl_load_library() 178 * 179 * This is used to dynamically load DLLs using the most secure method available 180 * for the version of Windows that we are running on. 181 * 182 * Parameters: 183 * 184 * filename [in] - The filename or full path of the DLL to load. If only the 185 * filename is passed then the DLL will be loaded from the 186 * Windows system directory. 187 * 188 * Returns the handle of the module on success; otherwise NULL. 189 */ 190 static HMODULE curl_load_library(LPCTSTR filename) 191 { 192 #if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) 193 HMODULE hModule = NULL; 194 LOADLIBRARYEX_FN pLoadLibraryEx = NULL; 195 196 /* Get a handle to kernel32 so we can access its functions at runtime */ 197 HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32")); 198 if(!hKernel32) 199 return NULL; 200 201 /* Attempt to find LoadLibraryEx() which is only available on Windows 2000 202 and above */ 203 pLoadLibraryEx = 204 CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN, 205 (GetProcAddress(hKernel32, LOADLIBARYEX))); 206 207 /* Detect if there is already a path in the filename and load the library if 208 there is. Note: Both back slashes and forward slashes have been supported 209 since the earlier days of DOS at an API level although they are not 210 supported by command prompt */ 211 if(_tcspbrk(filename, TEXT("\\/"))) { 212 /** !checksrc! disable BANNEDFUNC 1 **/ 213 hModule = pLoadLibraryEx ? 214 pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : 215 LoadLibrary(filename); 216 } 217 /* Detect if KB2533623 is installed, as LOAD_LIBRARY_SEARCH_SYSTEM32 is only 218 supported on Windows Vista, Windows Server 2008, Windows 7 and Windows 219 Server 2008 R2 with this patch or natively on Windows 8 and above */ 220 else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) { 221 /* Load the DLL from the Windows system directory */ 222 hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); 223 } 224 else { 225 /* Attempt to get the Windows system path */ 226 UINT systemdirlen = GetSystemDirectory(NULL, 0); 227 if(systemdirlen) { 228 /* Allocate space for the full DLL path (Room for the null-terminator 229 is included in systemdirlen) */ 230 size_t filenamelen = _tcslen(filename); 231 TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen)); 232 if(path && GetSystemDirectory(path, systemdirlen)) { 233 /* Calculate the full DLL path */ 234 _tcscpy(path + _tcslen(path), TEXT("\\")); 235 _tcscpy(path + _tcslen(path), filename); 236 237 /* Load the DLL from the Windows system directory */ 238 /** !checksrc! disable BANNEDFUNC 1 **/ 239 hModule = pLoadLibraryEx ? 240 pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : 241 LoadLibrary(path); 242 } 243 free(path); 244 } 245 } 246 return hModule; 247 #else 248 /* the Universal Windows Platform (UWP) cannot do this */ 249 (void)filename; 250 return NULL; 251 #endif 252 } 253 #endif /* !HAVE_IF_NAMETOINDEX */ 254 255 #endif /* _WIN32 */