Annotation of embedaddon/curl/lib/system_win32.c, revision 1.1
1.1 ! misho 1: /***************************************************************************
! 2: * _ _ ____ _
! 3: * Project ___| | | | _ \| |
! 4: * / __| | | | |_) | |
! 5: * | (__| |_| | _ <| |___
! 6: * \___|\___/|_| \_\_____|
! 7: *
! 8: * Copyright (C) 2016 - 2020, 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.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: #include "curl_sspi.h"
! 30: #include "warnless.h"
! 31:
! 32: /* The last #include files should be: */
! 33: #include "curl_memory.h"
! 34: #include "memdebug.h"
! 35:
! 36: LARGE_INTEGER Curl_freq;
! 37: bool Curl_isVistaOrGreater;
! 38:
! 39: /* Handle of iphlpapp.dll */
! 40: static HMODULE s_hIpHlpApiDll = NULL;
! 41:
! 42: /* Pointer to the if_nametoindex function */
! 43: IF_NAMETOINDEX_FN Curl_if_nametoindex = NULL;
! 44:
! 45: /* Curl_win32_init() performs win32 global initialization */
! 46: CURLcode Curl_win32_init(long flags)
! 47: {
! 48: /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which
! 49: is just for Winsock at the moment. Any required win32 initialization
! 50: should take place after this block. */
! 51: if(flags & CURL_GLOBAL_WIN32) {
! 52: #ifdef USE_WINSOCK
! 53: WORD wVersionRequested;
! 54: WSADATA wsaData;
! 55: int res;
! 56:
! 57: #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
! 58: #error IPV6_requires_winsock2
! 59: #endif
! 60:
! 61: wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
! 62:
! 63: res = WSAStartup(wVersionRequested, &wsaData);
! 64:
! 65: if(res != 0)
! 66: /* Tell the user that we couldn't 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 couldn't 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: s_hIpHlpApiDll = Curl_load_library(TEXT("iphlpapi.dll"));
! 99: if(s_hIpHlpApiDll) {
! 100: /* Get the address of the if_nametoindex function */
! 101: IF_NAMETOINDEX_FN pIfNameToIndex =
! 102: CURLX_FUNCTION_CAST(IF_NAMETOINDEX_FN,
! 103: (GetProcAddress(s_hIpHlpApiDll, "if_nametoindex")));
! 104:
! 105: if(pIfNameToIndex)
! 106: Curl_if_nametoindex = pIfNameToIndex;
! 107: }
! 108:
! 109: if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
! 110: VERSION_GREATER_THAN_EQUAL)) {
! 111: Curl_isVistaOrGreater = TRUE;
! 112: }
! 113: else
! 114: Curl_isVistaOrGreater = FALSE;
! 115:
! 116: QueryPerformanceFrequency(&Curl_freq);
! 117: return CURLE_OK;
! 118: }
! 119:
! 120: /* Curl_win32_cleanup() is the opposite of Curl_win32_init() */
! 121: void Curl_win32_cleanup(long init_flags)
! 122: {
! 123: if(s_hIpHlpApiDll) {
! 124: FreeLibrary(s_hIpHlpApiDll);
! 125: s_hIpHlpApiDll = NULL;
! 126: Curl_if_nametoindex = NULL;
! 127: }
! 128:
! 129: #ifdef USE_WINDOWS_SSPI
! 130: Curl_sspi_global_cleanup();
! 131: #endif
! 132:
! 133: if(init_flags & CURL_GLOBAL_WIN32) {
! 134: #ifdef USE_WINSOCK
! 135: WSACleanup();
! 136: #endif
! 137: }
! 138: }
! 139:
! 140: #if !defined(LOAD_WITH_ALTERED_SEARCH_PATH)
! 141: #define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008
! 142: #endif
! 143:
! 144: #if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
! 145: #define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
! 146: #endif
! 147:
! 148: /* We use our own typedef here since some headers might lack these */
! 149: typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
! 150:
! 151: /* See function definitions in winbase.h */
! 152: #ifdef UNICODE
! 153: # ifdef _WIN32_WCE
! 154: # define LOADLIBARYEX L"LoadLibraryExW"
! 155: # else
! 156: # define LOADLIBARYEX "LoadLibraryExW"
! 157: # endif
! 158: #else
! 159: # define LOADLIBARYEX "LoadLibraryExA"
! 160: #endif
! 161:
! 162: /*
! 163: * Curl_verify_windows_version()
! 164: *
! 165: * This is used to verify if we are running on a specific windows version.
! 166: *
! 167: * Parameters:
! 168: *
! 169: * majorVersion [in] - The major version number.
! 170: * minorVersion [in] - The minor version number.
! 171: * platform [in] - The optional platform identifier.
! 172: * condition [in] - The test condition used to specifier whether we are
! 173: * checking a version less then, equal to or greater than
! 174: * what is specified in the major and minor version
! 175: * numbers.
! 176: *
! 177: * Returns TRUE if matched; otherwise FALSE.
! 178: */
! 179: bool Curl_verify_windows_version(const unsigned int majorVersion,
! 180: const unsigned int minorVersion,
! 181: const PlatformIdentifier platform,
! 182: const VersionCondition condition)
! 183: {
! 184: bool matched = FALSE;
! 185:
! 186: #if defined(CURL_WINDOWS_APP)
! 187: /* We have no way to determine the Windows version from Windows apps,
! 188: so let's assume we're running on the target Windows version. */
! 189: const WORD fullVersion = MAKEWORD(minorVersion, majorVersion);
! 190: const WORD targetVersion = (WORD)_WIN32_WINNT;
! 191:
! 192: switch(condition) {
! 193: case VERSION_LESS_THAN:
! 194: matched = targetVersion < fullVersion;
! 195: break;
! 196:
! 197: case VERSION_LESS_THAN_EQUAL:
! 198: matched = targetVersion <= fullVersion;
! 199: break;
! 200:
! 201: case VERSION_EQUAL:
! 202: matched = targetVersion == fullVersion;
! 203: break;
! 204:
! 205: case VERSION_GREATER_THAN_EQUAL:
! 206: matched = targetVersion >= fullVersion;
! 207: break;
! 208:
! 209: case VERSION_GREATER_THAN:
! 210: matched = targetVersion > fullVersion;
! 211: break;
! 212: }
! 213:
! 214: if(matched && (platform == PLATFORM_WINDOWS)) {
! 215: /* we're always running on PLATFORM_WINNT */
! 216: matched = FALSE;
! 217: }
! 218: #elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
! 219: (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
! 220: OSVERSIONINFO osver;
! 221:
! 222: memset(&osver, 0, sizeof(osver));
! 223: osver.dwOSVersionInfoSize = sizeof(osver);
! 224:
! 225: /* Find out Windows version */
! 226: if(GetVersionEx(&osver)) {
! 227: /* Verify the Operating System version number */
! 228: switch(condition) {
! 229: case VERSION_LESS_THAN:
! 230: if(osver.dwMajorVersion < majorVersion ||
! 231: (osver.dwMajorVersion == majorVersion &&
! 232: osver.dwMinorVersion < minorVersion))
! 233: matched = TRUE;
! 234: break;
! 235:
! 236: case VERSION_LESS_THAN_EQUAL:
! 237: if(osver.dwMajorVersion < majorVersion ||
! 238: (osver.dwMajorVersion == majorVersion &&
! 239: osver.dwMinorVersion <= minorVersion))
! 240: matched = TRUE;
! 241: break;
! 242:
! 243: case VERSION_EQUAL:
! 244: if(osver.dwMajorVersion == majorVersion &&
! 245: osver.dwMinorVersion == minorVersion)
! 246: matched = TRUE;
! 247: break;
! 248:
! 249: case VERSION_GREATER_THAN_EQUAL:
! 250: if(osver.dwMajorVersion > majorVersion ||
! 251: (osver.dwMajorVersion == majorVersion &&
! 252: osver.dwMinorVersion >= minorVersion))
! 253: matched = TRUE;
! 254: break;
! 255:
! 256: case VERSION_GREATER_THAN:
! 257: if(osver.dwMajorVersion > majorVersion ||
! 258: (osver.dwMajorVersion == majorVersion &&
! 259: osver.dwMinorVersion > minorVersion))
! 260: matched = TRUE;
! 261: break;
! 262: }
! 263:
! 264: /* Verify the platform identifier (if necessary) */
! 265: if(matched) {
! 266: switch(platform) {
! 267: case PLATFORM_WINDOWS:
! 268: if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
! 269: matched = FALSE;
! 270: break;
! 271:
! 272: case PLATFORM_WINNT:
! 273: if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
! 274: matched = FALSE;
! 275:
! 276: default: /* like platform == PLATFORM_DONT_CARE */
! 277: break;
! 278: }
! 279: }
! 280: }
! 281: #else
! 282: ULONGLONG cm = 0;
! 283: OSVERSIONINFOEX osver;
! 284: BYTE majorCondition;
! 285: BYTE minorCondition;
! 286: BYTE spMajorCondition;
! 287: BYTE spMinorCondition;
! 288:
! 289: switch(condition) {
! 290: case VERSION_LESS_THAN:
! 291: majorCondition = VER_LESS;
! 292: minorCondition = VER_LESS;
! 293: spMajorCondition = VER_LESS_EQUAL;
! 294: spMinorCondition = VER_LESS_EQUAL;
! 295: break;
! 296:
! 297: case VERSION_LESS_THAN_EQUAL:
! 298: majorCondition = VER_LESS_EQUAL;
! 299: minorCondition = VER_LESS_EQUAL;
! 300: spMajorCondition = VER_LESS_EQUAL;
! 301: spMinorCondition = VER_LESS_EQUAL;
! 302: break;
! 303:
! 304: case VERSION_EQUAL:
! 305: majorCondition = VER_EQUAL;
! 306: minorCondition = VER_EQUAL;
! 307: spMajorCondition = VER_GREATER_EQUAL;
! 308: spMinorCondition = VER_GREATER_EQUAL;
! 309: break;
! 310:
! 311: case VERSION_GREATER_THAN_EQUAL:
! 312: majorCondition = VER_GREATER_EQUAL;
! 313: minorCondition = VER_GREATER_EQUAL;
! 314: spMajorCondition = VER_GREATER_EQUAL;
! 315: spMinorCondition = VER_GREATER_EQUAL;
! 316: break;
! 317:
! 318: case VERSION_GREATER_THAN:
! 319: majorCondition = VER_GREATER;
! 320: minorCondition = VER_GREATER;
! 321: spMajorCondition = VER_GREATER_EQUAL;
! 322: spMinorCondition = VER_GREATER_EQUAL;
! 323: break;
! 324:
! 325: default:
! 326: return FALSE;
! 327: }
! 328:
! 329: memset(&osver, 0, sizeof(osver));
! 330: osver.dwOSVersionInfoSize = sizeof(osver);
! 331: osver.dwMajorVersion = majorVersion;
! 332: osver.dwMinorVersion = minorVersion;
! 333: if(platform == PLATFORM_WINDOWS)
! 334: osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
! 335: else if(platform == PLATFORM_WINNT)
! 336: osver.dwPlatformId = VER_PLATFORM_WIN32_NT;
! 337:
! 338: cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition);
! 339: cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition);
! 340: cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition);
! 341: cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition);
! 342: if(platform != PLATFORM_DONT_CARE)
! 343: cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
! 344:
! 345: if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
! 346: VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
! 347: cm))
! 348: matched = TRUE;
! 349: #endif
! 350:
! 351: return matched;
! 352: }
! 353:
! 354: /*
! 355: * Curl_load_library()
! 356: *
! 357: * This is used to dynamically load DLLs using the most secure method available
! 358: * for the version of Windows that we are running on.
! 359: *
! 360: * Parameters:
! 361: *
! 362: * filename [in] - The filename or full path of the DLL to load. If only the
! 363: * filename is passed then the DLL will be loaded from the
! 364: * Windows system directory.
! 365: *
! 366: * Returns the handle of the module on success; otherwise NULL.
! 367: */
! 368: HMODULE Curl_load_library(LPCTSTR filename)
! 369: {
! 370: #ifndef CURL_WINDOWS_APP
! 371: HMODULE hModule = NULL;
! 372: LOADLIBRARYEX_FN pLoadLibraryEx = NULL;
! 373:
! 374: /* Get a handle to kernel32 so we can access it's functions at runtime */
! 375: HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32"));
! 376: if(!hKernel32)
! 377: return NULL;
! 378:
! 379: /* Attempt to find LoadLibraryEx() which is only available on Windows 2000
! 380: and above */
! 381: pLoadLibraryEx =
! 382: CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN,
! 383: (GetProcAddress(hKernel32, LOADLIBARYEX)));
! 384:
! 385: /* Detect if there's already a path in the filename and load the library if
! 386: there is. Note: Both back slashes and forward slashes have been supported
! 387: since the earlier days of DOS at an API level although they are not
! 388: supported by command prompt */
! 389: if(_tcspbrk(filename, TEXT("\\/"))) {
! 390: /** !checksrc! disable BANNEDFUNC 1 **/
! 391: hModule = pLoadLibraryEx ?
! 392: pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
! 393: LoadLibrary(filename);
! 394: }
! 395: /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
! 396: supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
! 397: Server 2008 R2 with this patch or natively on Windows 8 and above */
! 398: else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
! 399: /* Load the DLL from the Windows system directory */
! 400: hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
! 401: }
! 402: else {
! 403: /* Attempt to get the Windows system path */
! 404: UINT systemdirlen = GetSystemDirectory(NULL, 0);
! 405: if(systemdirlen) {
! 406: /* Allocate space for the full DLL path (Room for the null terminator
! 407: is included in systemdirlen) */
! 408: size_t filenamelen = _tcslen(filename);
! 409: TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen));
! 410: if(path && GetSystemDirectory(path, systemdirlen)) {
! 411: /* Calculate the full DLL path */
! 412: _tcscpy(path + _tcslen(path), TEXT("\\"));
! 413: _tcscpy(path + _tcslen(path), filename);
! 414:
! 415: /* Load the DLL from the Windows system directory */
! 416: /** !checksrc! disable BANNEDFUNC 1 **/
! 417: hModule = pLoadLibraryEx ?
! 418: pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
! 419: LoadLibrary(path);
! 420:
! 421: }
! 422: free(path);
! 423: }
! 424: }
! 425: return hModule;
! 426: #else
! 427: /* the Universal Windows Platform (UWP) can't do this */
! 428: (void)filename;
! 429: return NULL;
! 430: #endif
! 431: }
! 432:
! 433: #endif /* WIN32 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>