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>