1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 2016, Steve Holme, <steve_holme (at) 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.haxx.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 ***************************************************************************/ 22 23 #include "curl_setup.h" 24 25 #if defined(WIN32) 26 27 #include <curl/curl.h> 28 #include "system_win32.h" 29 30 /* The last #include files should be: */ 31 #include "curl_memory.h" 32 #include "memdebug.h" 33 34 #if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \ 35 defined(USE_WINSOCK)) 36 37 38 #if !defined(LOAD_WITH_ALTERED_SEARCH_PATH) 39 #define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008 40 #endif 41 42 #if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32) 43 #define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 44 #endif 45 46 /* We use our own typedef here since some headers might lack these */ 47 typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); 48 49 /* See function definitions in winbase.h */ 50 #ifdef UNICODE 51 # ifdef _WIN32_WCE 52 # define LOADLIBARYEX L"LoadLibraryExW" 53 # else 54 # define LOADLIBARYEX "LoadLibraryExW" 55 # endif 56 #else 57 # define LOADLIBARYEX "LoadLibraryExA" 58 #endif 59 60 #endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */ 61 62 /* 63 * Curl_verify_windows_version() 64 * 65 * This is used to verify if we are running on a specific windows version. 66 * 67 * Parameters: 68 * 69 * majorVersion [in] - The major version number. 70 * minorVersion [in] - The minor version number. 71 * platform [in] - The optional platform identifer. 72 * condition [in] - The test condition used to specifier whether we are 73 * checking a version less then, equal to or greater than 74 * what is specified in the major and minor version 75 * numbers. 76 * 77 * Returns TRUE if matched; otherwise FALSE. 78 */ 79 bool Curl_verify_windows_version(const unsigned int majorVersion, 80 const unsigned int minorVersion, 81 const PlatformIdentifier platform, 82 const VersionCondition condition) 83 { 84 bool matched = FALSE; 85 86 #if defined(CURL_WINDOWS_APP) 87 /* We have no way to determine the Windows version from Windows apps, 88 so let's assume we're running on the target Windows version. */ 89 const WORD fullVersion = MAKEWORD(minorVersion, majorVersion); 90 const WORD targetVersion = (WORD)_WIN32_WINNT; 91 92 switch(condition) { 93 case VERSION_LESS_THAN: 94 matched = targetVersion < fullVersion; 95 break; 96 97 case VERSION_LESS_THAN_EQUAL: 98 matched = targetVersion <= fullVersion; 99 break; 100 101 case VERSION_EQUAL: 102 matched = targetVersion == fullVersion; 103 break; 104 105 case VERSION_GREATER_THAN_EQUAL: 106 matched = targetVersion >= fullVersion; 107 break; 108 109 case VERSION_GREATER_THAN: 110 matched = targetVersion > fullVersion; 111 break; 112 } 113 114 if(matched && (platform == PLATFORM_WINDOWS)) { 115 /* we're always running on PLATFORM_WINNT */ 116 matched = FALSE; 117 } 118 #elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \ 119 (_WIN32_WINNT < _WIN32_WINNT_WIN2K) 120 OSVERSIONINFO osver; 121 122 memset(&osver, 0, sizeof(osver)); 123 osver.dwOSVersionInfoSize = sizeof(osver); 124 125 /* Find out Windows version */ 126 if(GetVersionEx(&osver)) { 127 /* Verify the Operating System version number */ 128 switch(condition) { 129 case VERSION_LESS_THAN: 130 if(osver.dwMajorVersion < majorVersion || 131 (osver.dwMajorVersion == majorVersion && 132 osver.dwMinorVersion < minorVersion)) 133 matched = TRUE; 134 break; 135 136 case VERSION_LESS_THAN_EQUAL: 137 if(osver.dwMajorVersion <= majorVersion && 138 osver.dwMinorVersion <= minorVersion) 139 matched = TRUE; 140 break; 141 142 case VERSION_EQUAL: 143 if(osver.dwMajorVersion == majorVersion && 144 osver.dwMinorVersion == minorVersion) 145 matched = TRUE; 146 break; 147 148 case VERSION_GREATER_THAN_EQUAL: 149 if(osver.dwMajorVersion >= majorVersion && 150 osver.dwMinorVersion >= minorVersion) 151 matched = TRUE; 152 break; 153 154 case VERSION_GREATER_THAN: 155 if(osver.dwMajorVersion > majorVersion || 156 (osver.dwMajorVersion == majorVersion && 157 osver.dwMinorVersion > minorVersion)) 158 matched = TRUE; 159 break; 160 } 161 162 /* Verify the platform identifier (if necessary) */ 163 if(matched) { 164 switch(platform) { 165 case PLATFORM_WINDOWS: 166 if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) 167 matched = FALSE; 168 break; 169 170 case PLATFORM_WINNT: 171 if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT) 172 matched = FALSE; 173 174 default: /* like platform == PLATFORM_DONT_CARE */ 175 break; 176 } 177 } 178 } 179 #else 180 ULONGLONG cm = 0; 181 OSVERSIONINFOEX osver; 182 BYTE majorCondition; 183 BYTE minorCondition; 184 BYTE spMajorCondition; 185 BYTE spMinorCondition; 186 187 switch(condition) { 188 case VERSION_LESS_THAN: 189 majorCondition = VER_LESS; 190 minorCondition = VER_LESS; 191 spMajorCondition = VER_LESS_EQUAL; 192 spMinorCondition = VER_LESS_EQUAL; 193 break; 194 195 case VERSION_LESS_THAN_EQUAL: 196 majorCondition = VER_LESS_EQUAL; 197 minorCondition = VER_LESS_EQUAL; 198 spMajorCondition = VER_LESS_EQUAL; 199 spMinorCondition = VER_LESS_EQUAL; 200 break; 201 202 case VERSION_EQUAL: 203 majorCondition = VER_EQUAL; 204 minorCondition = VER_EQUAL; 205 spMajorCondition = VER_GREATER_EQUAL; 206 spMinorCondition = VER_GREATER_EQUAL; 207 break; 208 209 case VERSION_GREATER_THAN_EQUAL: 210 majorCondition = VER_GREATER_EQUAL; 211 minorCondition = VER_GREATER_EQUAL; 212 spMajorCondition = VER_GREATER_EQUAL; 213 spMinorCondition = VER_GREATER_EQUAL; 214 break; 215 216 case VERSION_GREATER_THAN: 217 majorCondition = VER_GREATER; 218 minorCondition = VER_GREATER; 219 spMajorCondition = VER_GREATER_EQUAL; 220 spMinorCondition = VER_GREATER_EQUAL; 221 break; 222 223 default: 224 return FALSE; 225 } 226 227 memset(&osver, 0, sizeof(osver)); 228 osver.dwOSVersionInfoSize = sizeof(osver); 229 osver.dwMajorVersion = majorVersion; 230 osver.dwMinorVersion = minorVersion; 231 if(platform == PLATFORM_WINDOWS) 232 osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; 233 else if(platform == PLATFORM_WINNT) 234 osver.dwPlatformId = VER_PLATFORM_WIN32_NT; 235 236 cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition); 237 cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition); 238 cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition); 239 cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition); 240 if(platform != PLATFORM_DONT_CARE) 241 cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL); 242 243 if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION | 244 VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), 245 cm)) 246 matched = TRUE; 247 #endif 248 249 return matched; 250 } 251 252 #if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \ 253 defined(USE_WINSOCK)) 254 255 /* 256 * Curl_load_library() 257 * 258 * This is used to dynamically load DLLs using the most secure method available 259 * for the version of Windows that we are running on. 260 * 261 * Parameters: 262 * 263 * filename [in] - The filename or full path of the DLL to load. If only the 264 * filename is passed then the DLL will be loaded from the 265 * Windows system directory. 266 * 267 * Returns the handle of the module on success; otherwise NULL. 268 */ 269 HMODULE Curl_load_library(LPCTSTR filename) 270 { 271 HMODULE hModule = NULL; 272 LOADLIBRARYEX_FN pLoadLibraryEx = NULL; 273 274 /* Get a handle to kernel32 so we can access it's functions at runtime */ 275 HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32")); 276 if(!hKernel32) 277 return NULL; 278 279 /* Attempt to find LoadLibraryEx() which is only available on Windows 2000 280 and above */ 281 pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX); 282 283 /* Detect if there's already a path in the filename and load the library if 284 there is. Note: Both back slashes and forward slashes have been supported 285 since the earlier days of DOS at an API level although they are not 286 supported by command prompt */ 287 if(_tcspbrk(filename, TEXT("\\/"))) { 288 /** !checksrc! disable BANNEDFUNC 1 **/ 289 hModule = pLoadLibraryEx ? 290 pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : 291 LoadLibrary(filename); 292 } 293 /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only 294 supported on Windows Vista, Windows Server 2008, Windows 7 and Windows 295 Server 2008 R2 with this patch or natively on Windows 8 and above */ 296 else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) { 297 /* Load the DLL from the Windows system directory */ 298 hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); 299 } 300 else { 301 /* Attempt to get the Windows system path */ 302 UINT systemdirlen = GetSystemDirectory(NULL, 0); 303 if(systemdirlen) { 304 /* Allocate space for the full DLL path (Room for the null terminator 305 is included in systemdirlen) */ 306 size_t filenamelen = _tcslen(filename); 307 TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen)); 308 if(path && GetSystemDirectory(path, systemdirlen)) { 309 /* Calculate the full DLL path */ 310 _tcscpy(path + _tcslen(path), TEXT("\\")); 311 _tcscpy(path + _tcslen(path), filename); 312 313 /* Load the DLL from the Windows system directory */ 314 /** !checksrc! disable BANNEDFUNC 1 **/ 315 hModule = pLoadLibraryEx ? 316 pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : 317 LoadLibrary(path); 318 319 } 320 free(path); 321 } 322 } 323 324 return hModule; 325 } 326 327 #endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */ 328 329 #endif /* WIN32 */ 330