Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 2016 - 2017, 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 identifier.
     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