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