File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / system_win32.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (4 years, 1 month ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    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>