Annotation of embedaddon/curl/lib/system_win32.c, revision 1.1.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>