system_win32.c 13 KB

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