system_win32.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. #include "curl_setup.h"
  23. #if defined(WIN32)
  24. #include <curl/curl.h>
  25. #include "system_win32.h"
  26. #include "curl_sspi.h"
  27. #include "warnless.h"
  28. /* The last #include files should be: */
  29. #include "curl_memory.h"
  30. #include "memdebug.h"
  31. LARGE_INTEGER Curl_freq;
  32. bool Curl_isVistaOrGreater;
  33. /* Handle of iphlpapp.dll */
  34. static HMODULE s_hIpHlpApiDll = NULL;
  35. /* Pointer to the if_nametoindex function */
  36. IF_NAMETOINDEX_FN Curl_if_nametoindex = NULL;
  37. /* Curl_win32_init() performs win32 global initialization */
  38. CURLcode Curl_win32_init(long flags)
  39. {
  40. /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which
  41. is just for Winsock at the moment. Any required win32 initialization
  42. should take place after this block. */
  43. if(flags & CURL_GLOBAL_WIN32) {
  44. #ifdef USE_WINSOCK
  45. WORD wVersionRequested;
  46. WSADATA wsaData;
  47. int res;
  48. #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
  49. #error IPV6_requires_winsock2
  50. #endif
  51. wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
  52. res = WSAStartup(wVersionRequested, &wsaData);
  53. if(res != 0)
  54. /* Tell the user that we couldn't find a usable */
  55. /* winsock.dll. */
  56. return CURLE_FAILED_INIT;
  57. /* Confirm that the Windows Sockets DLL supports what we need.*/
  58. /* Note that if the DLL supports versions greater */
  59. /* than wVersionRequested, it will still return */
  60. /* wVersionRequested in wVersion. wHighVersion contains the */
  61. /* highest supported version. */
  62. if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
  63. HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
  64. /* Tell the user that we couldn't find a usable */
  65. /* winsock.dll. */
  66. WSACleanup();
  67. return CURLE_FAILED_INIT;
  68. }
  69. /* The Windows Sockets DLL is acceptable. Proceed. */
  70. #elif defined(USE_LWIPSOCK)
  71. lwip_init();
  72. #endif
  73. } /* CURL_GLOBAL_WIN32 */
  74. #ifdef USE_WINDOWS_SSPI
  75. {
  76. CURLcode result = Curl_sspi_global_init();
  77. if(result)
  78. return result;
  79. }
  80. #endif
  81. s_hIpHlpApiDll = Curl_load_library(TEXT("iphlpapi.dll"));
  82. if(s_hIpHlpApiDll) {
  83. /* Get the address of the if_nametoindex function */
  84. IF_NAMETOINDEX_FN pIfNameToIndex =
  85. CURLX_FUNCTION_CAST(IF_NAMETOINDEX_FN,
  86. (GetProcAddress(s_hIpHlpApiDll, "if_nametoindex")));
  87. if(pIfNameToIndex)
  88. Curl_if_nametoindex = pIfNameToIndex;
  89. }
  90. if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
  91. VERSION_GREATER_THAN_EQUAL)) {
  92. Curl_isVistaOrGreater = TRUE;
  93. }
  94. else
  95. Curl_isVistaOrGreater = FALSE;
  96. QueryPerformanceFrequency(&Curl_freq);
  97. return CURLE_OK;
  98. }
  99. /* Curl_win32_cleanup() is the opposite of Curl_win32_init() */
  100. void Curl_win32_cleanup(long init_flags)
  101. {
  102. if(s_hIpHlpApiDll) {
  103. FreeLibrary(s_hIpHlpApiDll);
  104. s_hIpHlpApiDll = NULL;
  105. Curl_if_nametoindex = NULL;
  106. }
  107. #ifdef USE_WINDOWS_SSPI
  108. Curl_sspi_global_cleanup();
  109. #endif
  110. if(init_flags & CURL_GLOBAL_WIN32) {
  111. #ifdef USE_WINSOCK
  112. WSACleanup();
  113. #endif
  114. }
  115. }
  116. #if !defined(LOAD_WITH_ALTERED_SEARCH_PATH)
  117. #define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008
  118. #endif
  119. #if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
  120. #define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
  121. #endif
  122. /* We use our own typedef here since some headers might lack these */
  123. typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
  124. /* See function definitions in winbase.h */
  125. #ifdef UNICODE
  126. # ifdef _WIN32_WCE
  127. # define LOADLIBARYEX L"LoadLibraryExW"
  128. # else
  129. # define LOADLIBARYEX "LoadLibraryExW"
  130. # endif
  131. #else
  132. # define LOADLIBARYEX "LoadLibraryExA"
  133. #endif
  134. /*
  135. * Curl_verify_windows_version()
  136. *
  137. * This is used to verify if we are running on a specific windows version.
  138. *
  139. * Parameters:
  140. *
  141. * majorVersion [in] - The major version number.
  142. * minorVersion [in] - The minor version number.
  143. * platform [in] - The optional platform identifier.
  144. * condition [in] - The test condition used to specifier whether we are
  145. * checking a version less then, equal to or greater than
  146. * what is specified in the major and minor version
  147. * numbers.
  148. *
  149. * Returns TRUE if matched; otherwise FALSE.
  150. */
  151. bool Curl_verify_windows_version(const unsigned int majorVersion,
  152. const unsigned int minorVersion,
  153. const PlatformIdentifier platform,
  154. const VersionCondition condition)
  155. {
  156. bool matched = FALSE;
  157. #if defined(CURL_WINDOWS_APP)
  158. /* We have no way to determine the Windows version from Windows apps,
  159. so let's assume we're running on the target Windows version. */
  160. const WORD fullVersion = MAKEWORD(minorVersion, majorVersion);
  161. const WORD targetVersion = (WORD)_WIN32_WINNT;
  162. switch(condition) {
  163. case VERSION_LESS_THAN:
  164. matched = targetVersion < fullVersion;
  165. break;
  166. case VERSION_LESS_THAN_EQUAL:
  167. matched = targetVersion <= fullVersion;
  168. break;
  169. case VERSION_EQUAL:
  170. matched = targetVersion == fullVersion;
  171. break;
  172. case VERSION_GREATER_THAN_EQUAL:
  173. matched = targetVersion >= fullVersion;
  174. break;
  175. case VERSION_GREATER_THAN:
  176. matched = targetVersion > fullVersion;
  177. break;
  178. }
  179. if(matched && (platform == PLATFORM_WINDOWS)) {
  180. /* we're always running on PLATFORM_WINNT */
  181. matched = FALSE;
  182. }
  183. #elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
  184. (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
  185. OSVERSIONINFO osver;
  186. memset(&osver, 0, sizeof(osver));
  187. osver.dwOSVersionInfoSize = sizeof(osver);
  188. /* Find out Windows version */
  189. if(GetVersionEx(&osver)) {
  190. /* Verify the Operating System version number */
  191. switch(condition) {
  192. case VERSION_LESS_THAN:
  193. if(osver.dwMajorVersion < majorVersion ||
  194. (osver.dwMajorVersion == majorVersion &&
  195. osver.dwMinorVersion < minorVersion))
  196. matched = TRUE;
  197. break;
  198. case VERSION_LESS_THAN_EQUAL:
  199. if(osver.dwMajorVersion < majorVersion ||
  200. (osver.dwMajorVersion == majorVersion &&
  201. osver.dwMinorVersion <= minorVersion))
  202. matched = TRUE;
  203. break;
  204. case VERSION_EQUAL:
  205. if(osver.dwMajorVersion == majorVersion &&
  206. osver.dwMinorVersion == minorVersion)
  207. matched = TRUE;
  208. break;
  209. case VERSION_GREATER_THAN_EQUAL:
  210. if(osver.dwMajorVersion > majorVersion ||
  211. (osver.dwMajorVersion == majorVersion &&
  212. osver.dwMinorVersion >= minorVersion))
  213. matched = TRUE;
  214. break;
  215. case VERSION_GREATER_THAN:
  216. if(osver.dwMajorVersion > majorVersion ||
  217. (osver.dwMajorVersion == majorVersion &&
  218. osver.dwMinorVersion > minorVersion))
  219. matched = TRUE;
  220. break;
  221. }
  222. /* Verify the platform identifier (if necessary) */
  223. if(matched) {
  224. switch(platform) {
  225. case PLATFORM_WINDOWS:
  226. if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
  227. matched = FALSE;
  228. break;
  229. case PLATFORM_WINNT:
  230. if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
  231. matched = FALSE;
  232. default: /* like platform == PLATFORM_DONT_CARE */
  233. break;
  234. }
  235. }
  236. }
  237. #else
  238. ULONGLONG cm = 0;
  239. OSVERSIONINFOEX osver;
  240. BYTE majorCondition;
  241. BYTE minorCondition;
  242. BYTE spMajorCondition;
  243. BYTE spMinorCondition;
  244. switch(condition) {
  245. case VERSION_LESS_THAN:
  246. majorCondition = VER_LESS;
  247. minorCondition = VER_LESS;
  248. spMajorCondition = VER_LESS_EQUAL;
  249. spMinorCondition = VER_LESS_EQUAL;
  250. break;
  251. case VERSION_LESS_THAN_EQUAL:
  252. majorCondition = VER_LESS_EQUAL;
  253. minorCondition = VER_LESS_EQUAL;
  254. spMajorCondition = VER_LESS_EQUAL;
  255. spMinorCondition = VER_LESS_EQUAL;
  256. break;
  257. case VERSION_EQUAL:
  258. majorCondition = VER_EQUAL;
  259. minorCondition = VER_EQUAL;
  260. spMajorCondition = VER_GREATER_EQUAL;
  261. spMinorCondition = VER_GREATER_EQUAL;
  262. break;
  263. case VERSION_GREATER_THAN_EQUAL:
  264. majorCondition = VER_GREATER_EQUAL;
  265. minorCondition = VER_GREATER_EQUAL;
  266. spMajorCondition = VER_GREATER_EQUAL;
  267. spMinorCondition = VER_GREATER_EQUAL;
  268. break;
  269. case VERSION_GREATER_THAN:
  270. majorCondition = VER_GREATER;
  271. minorCondition = VER_GREATER;
  272. spMajorCondition = VER_GREATER_EQUAL;
  273. spMinorCondition = VER_GREATER_EQUAL;
  274. break;
  275. default:
  276. return FALSE;
  277. }
  278. memset(&osver, 0, sizeof(osver));
  279. osver.dwOSVersionInfoSize = sizeof(osver);
  280. osver.dwMajorVersion = majorVersion;
  281. osver.dwMinorVersion = minorVersion;
  282. if(platform == PLATFORM_WINDOWS)
  283. osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
  284. else if(platform == PLATFORM_WINNT)
  285. osver.dwPlatformId = VER_PLATFORM_WIN32_NT;
  286. cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition);
  287. cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition);
  288. cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition);
  289. cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition);
  290. if(platform != PLATFORM_DONT_CARE)
  291. cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
  292. if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
  293. VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
  294. cm))
  295. matched = TRUE;
  296. #endif
  297. return matched;
  298. }
  299. /*
  300. * Curl_load_library()
  301. *
  302. * This is used to dynamically load DLLs using the most secure method available
  303. * for the version of Windows that we are running on.
  304. *
  305. * Parameters:
  306. *
  307. * filename [in] - The filename or full path of the DLL to load. If only the
  308. * filename is passed then the DLL will be loaded from the
  309. * Windows system directory.
  310. *
  311. * Returns the handle of the module on success; otherwise NULL.
  312. */
  313. HMODULE Curl_load_library(LPCTSTR filename)
  314. {
  315. #ifndef CURL_WINDOWS_APP
  316. HMODULE hModule = NULL;
  317. LOADLIBRARYEX_FN pLoadLibraryEx = NULL;
  318. /* Get a handle to kernel32 so we can access it's functions at runtime */
  319. HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32"));
  320. if(!hKernel32)
  321. return NULL;
  322. /* Attempt to find LoadLibraryEx() which is only available on Windows 2000
  323. and above */
  324. pLoadLibraryEx =
  325. CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN,
  326. (GetProcAddress(hKernel32, LOADLIBARYEX)));
  327. /* Detect if there's already a path in the filename and load the library if
  328. there is. Note: Both back slashes and forward slashes have been supported
  329. since the earlier days of DOS at an API level although they are not
  330. supported by command prompt */
  331. if(_tcspbrk(filename, TEXT("\\/"))) {
  332. /** !checksrc! disable BANNEDFUNC 1 **/
  333. hModule = pLoadLibraryEx ?
  334. pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
  335. LoadLibrary(filename);
  336. }
  337. /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
  338. supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
  339. Server 2008 R2 with this patch or natively on Windows 8 and above */
  340. else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
  341. /* Load the DLL from the Windows system directory */
  342. hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
  343. }
  344. else {
  345. /* Attempt to get the Windows system path */
  346. UINT systemdirlen = GetSystemDirectory(NULL, 0);
  347. if(systemdirlen) {
  348. /* Allocate space for the full DLL path (Room for the null terminator
  349. is included in systemdirlen) */
  350. size_t filenamelen = _tcslen(filename);
  351. TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen));
  352. if(path && GetSystemDirectory(path, systemdirlen)) {
  353. /* Calculate the full DLL path */
  354. _tcscpy(path + _tcslen(path), TEXT("\\"));
  355. _tcscpy(path + _tcslen(path), filename);
  356. /* Load the DLL from the Windows system directory */
  357. /** !checksrc! disable BANNEDFUNC 1 **/
  358. hModule = pLoadLibraryEx ?
  359. pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
  360. LoadLibrary(path);
  361. }
  362. free(path);
  363. }
  364. }
  365. return hModule;
  366. #else
  367. /* the Universal Windows Platform (UWP) can't do this */
  368. (void)filename;
  369. return NULL;
  370. #endif
  371. }
  372. #endif /* WIN32 */