Home | History | Annotate | Download | only in lib
      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(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
     87     (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
     88   OSVERSIONINFO osver;
     89 
     90   memset(&osver, 0, sizeof(osver));
     91   osver.dwOSVersionInfoSize = sizeof(osver);
     92 
     93   /* Find out Windows version */
     94   if(GetVersionEx(&osver)) {
     95     /* Verify the Operating System version number */
     96     switch(condition) {
     97     case VERSION_LESS_THAN:
     98       if(osver.dwMajorVersion < majorVersion ||
     99         (osver.dwMajorVersion == majorVersion &&
    100          osver.dwMinorVersion < minorVersion))
    101         matched = TRUE;
    102       break;
    103 
    104     case VERSION_LESS_THAN_EQUAL:
    105       if(osver.dwMajorVersion <= majorVersion &&
    106          osver.dwMinorVersion <= minorVersion)
    107         matched = TRUE;
    108       break;
    109 
    110     case VERSION_EQUAL:
    111       if(osver.dwMajorVersion == majorVersion &&
    112          osver.dwMinorVersion == minorVersion)
    113         matched = TRUE;
    114       break;
    115 
    116     case VERSION_GREATER_THAN_EQUAL:
    117       if(osver.dwMajorVersion >= majorVersion &&
    118          osver.dwMinorVersion >= minorVersion)
    119         matched = TRUE;
    120       break;
    121 
    122     case VERSION_GREATER_THAN:
    123       if(osver.dwMajorVersion > majorVersion ||
    124         (osver.dwMajorVersion == majorVersion &&
    125          osver.dwMinorVersion > minorVersion))
    126         matched = TRUE;
    127       break;
    128     }
    129 
    130     /* Verify the platform identifier (if necessary) */
    131     if(matched && platform != PLATFORM_DONT_CARE) {
    132       switch(platform) {
    133       case PLATFORM_WINDOWS:
    134         if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
    135           matched = FALSE;
    136         break;
    137 
    138       case PLATFORM_WINNT:
    139         if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
    140           matched = FALSE;
    141       }
    142     }
    143   }
    144 #else
    145   ULONGLONG cm = 0;
    146   OSVERSIONINFOEX osver;
    147   BYTE majorCondition;
    148   BYTE minorCondition;
    149   BYTE spMajorCondition;
    150   BYTE spMinorCondition;
    151 
    152   switch(condition) {
    153   case VERSION_LESS_THAN:
    154     majorCondition = VER_LESS;
    155     minorCondition = VER_LESS;
    156     spMajorCondition = VER_LESS_EQUAL;
    157     spMinorCondition = VER_LESS_EQUAL;
    158     break;
    159 
    160   case VERSION_LESS_THAN_EQUAL:
    161     majorCondition = VER_LESS_EQUAL;
    162     minorCondition = VER_LESS_EQUAL;
    163     spMajorCondition = VER_LESS_EQUAL;
    164     spMinorCondition = VER_LESS_EQUAL;
    165     break;
    166 
    167   case VERSION_EQUAL:
    168     majorCondition = VER_EQUAL;
    169     minorCondition = VER_EQUAL;
    170     spMajorCondition = VER_GREATER_EQUAL;
    171     spMinorCondition = VER_GREATER_EQUAL;
    172     break;
    173 
    174   case VERSION_GREATER_THAN_EQUAL:
    175     majorCondition = VER_GREATER_EQUAL;
    176     minorCondition = VER_GREATER_EQUAL;
    177     spMajorCondition = VER_GREATER_EQUAL;
    178     spMinorCondition = VER_GREATER_EQUAL;
    179     break;
    180 
    181   case VERSION_GREATER_THAN:
    182     majorCondition = VER_GREATER;
    183     minorCondition = VER_GREATER;
    184     spMajorCondition = VER_GREATER_EQUAL;
    185     spMinorCondition = VER_GREATER_EQUAL;
    186     break;
    187 
    188   default:
    189     return FALSE;
    190   }
    191 
    192   memset(&osver, 0, sizeof(osver));
    193   osver.dwOSVersionInfoSize = sizeof(osver);
    194   osver.dwMajorVersion = majorVersion;
    195   osver.dwMinorVersion = minorVersion;
    196   if(platform == PLATFORM_WINDOWS)
    197     osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
    198   else if(platform == PLATFORM_WINNT)
    199     osver.dwPlatformId = VER_PLATFORM_WIN32_NT;
    200 
    201   cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition);
    202   cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition);
    203   cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition);
    204   cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition);
    205   if(platform != PLATFORM_DONT_CARE)
    206     cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
    207 
    208   if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
    209                                 VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
    210                        cm))
    211     matched = TRUE;
    212 #endif
    213 
    214   return matched;
    215 }
    216 
    217 #if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \
    218                                   defined(USE_WINSOCK))
    219 
    220 /*
    221  * Curl_load_library()
    222  *
    223  * This is used to dynamically load DLLs using the most secure method available
    224  * for the version of Windows that we are running on.
    225  *
    226  * Parameters:
    227  *
    228  * filename  [in] - The filename or full path of the DLL to load. If only the
    229  *                  filename is passed then the DLL will be loaded from the
    230  *                  Windows system directory.
    231  *
    232  * Returns the handle of the module on success; otherwise NULL.
    233  */
    234 HMODULE Curl_load_library(LPCTSTR filename)
    235 {
    236   HMODULE hModule = NULL;
    237   LOADLIBRARYEX_FN pLoadLibraryEx = NULL;
    238 
    239   /* Get a handle to kernel32 so we can access it's functions at runtime */
    240   HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32"));
    241   if(!hKernel32)
    242     return NULL;
    243 
    244   /* Attempt to find LoadLibraryEx() which is only available on Windows 2000
    245      and above */
    246   pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX);
    247 
    248   /* Detect if there's already a path in the filename and load the library if
    249      there is. Note: Both back slashes and forward slashes have been supported
    250      since the earlier days of DOS at an API level although they are not
    251      supported by command prompt */
    252   if(_tcspbrk(filename, TEXT("\\/"))) {
    253     /** !checksrc! disable BANNEDFUNC 1 **/
    254     hModule = pLoadLibraryEx ?
    255       pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
    256       LoadLibrary(filename);
    257   }
    258   /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
    259      supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
    260      Server 2008 R2 with this patch or natively on Windows 8 and above */
    261   else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
    262     /* Load the DLL from the Windows system directory */
    263     hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
    264   }
    265   else {
    266     /* Attempt to get the Windows system path */
    267     UINT systemdirlen = GetSystemDirectory(NULL, 0);
    268     if(systemdirlen) {
    269       /* Allocate space for the full DLL path (Room for the null terminator
    270          is included in systemdirlen) */
    271       size_t filenamelen = _tcslen(filename);
    272       TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen));
    273       if(path && GetSystemDirectory(path, systemdirlen)) {
    274         /* Calculate the full DLL path */
    275         _tcscpy(path + _tcslen(path), TEXT("\\"));
    276         _tcscpy(path + _tcslen(path), filename);
    277 
    278         /* Load the DLL from the Windows system directory */
    279         /** !checksrc! disable BANNEDFUNC 1 **/
    280         hModule = pLoadLibraryEx ?
    281           pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
    282           LoadLibrary(path);
    283 
    284       }
    285       free(path);
    286     }
    287   }
    288 
    289   return hModule;
    290 }
    291 
    292 #endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */
    293 
    294 #endif /* WIN32 */
    295