system_win32.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 2016 - 2017, 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 "warnless.h"
  27. /* The last #include files should be: */
  28. #include "curl_memory.h"
  29. #include "memdebug.h"
  30. #if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \
  31. defined(USE_WINSOCK))
  32. #if !defined(LOAD_WITH_ALTERED_SEARCH_PATH)
  33. #define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008
  34. #endif
  35. #if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
  36. #define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
  37. #endif
  38. /* We use our own typedef here since some headers might lack these */
  39. typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
  40. /* See function definitions in winbase.h */
  41. #ifdef UNICODE
  42. # ifdef _WIN32_WCE
  43. # define LOADLIBARYEX L"LoadLibraryExW"
  44. # else
  45. # define LOADLIBARYEX "LoadLibraryExW"
  46. # endif
  47. #else
  48. # define LOADLIBARYEX "LoadLibraryExA"
  49. #endif
  50. #endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */
  51. /*
  52. * Curl_verify_windows_version()
  53. *
  54. * This is used to verify if we are running on a specific windows version.
  55. *
  56. * Parameters:
  57. *
  58. * majorVersion [in] - The major version number.
  59. * minorVersion [in] - The minor version number.
  60. * platform [in] - The optional platform identifier.
  61. * condition [in] - The test condition used to specifier whether we are
  62. * checking a version less then, equal to or greater than
  63. * what is specified in the major and minor version
  64. * numbers.
  65. *
  66. * Returns TRUE if matched; otherwise FALSE.
  67. */
  68. bool Curl_verify_windows_version(const unsigned int majorVersion,
  69. const unsigned int minorVersion,
  70. const PlatformIdentifier platform,
  71. const VersionCondition condition)
  72. {
  73. bool matched = FALSE;
  74. #if defined(CURL_WINDOWS_APP)
  75. /* We have no way to determine the Windows version from Windows apps,
  76. so let's assume we're running on the target Windows version. */
  77. const WORD fullVersion = MAKEWORD(minorVersion, majorVersion);
  78. const WORD targetVersion = (WORD)_WIN32_WINNT;
  79. switch(condition) {
  80. case VERSION_LESS_THAN:
  81. matched = targetVersion < fullVersion;
  82. break;
  83. case VERSION_LESS_THAN_EQUAL:
  84. matched = targetVersion <= fullVersion;
  85. break;
  86. case VERSION_EQUAL:
  87. matched = targetVersion == fullVersion;
  88. break;
  89. case VERSION_GREATER_THAN_EQUAL:
  90. matched = targetVersion >= fullVersion;
  91. break;
  92. case VERSION_GREATER_THAN:
  93. matched = targetVersion > fullVersion;
  94. break;
  95. }
  96. if(matched && (platform == PLATFORM_WINDOWS)) {
  97. /* we're always running on PLATFORM_WINNT */
  98. matched = FALSE;
  99. }
  100. #elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
  101. (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
  102. OSVERSIONINFO osver;
  103. memset(&osver, 0, sizeof(osver));
  104. osver.dwOSVersionInfoSize = sizeof(osver);
  105. /* Find out Windows version */
  106. if(GetVersionEx(&osver)) {
  107. /* Verify the Operating System version number */
  108. switch(condition) {
  109. case VERSION_LESS_THAN:
  110. if(osver.dwMajorVersion < majorVersion ||
  111. (osver.dwMajorVersion == majorVersion &&
  112. osver.dwMinorVersion < minorVersion))
  113. matched = TRUE;
  114. break;
  115. case VERSION_LESS_THAN_EQUAL:
  116. if(osver.dwMajorVersion < majorVersion ||
  117. (osver.dwMajorVersion == majorVersion &&
  118. osver.dwMinorVersion <= minorVersion))
  119. matched = TRUE;
  120. break;
  121. case VERSION_EQUAL:
  122. if(osver.dwMajorVersion == majorVersion &&
  123. osver.dwMinorVersion == minorVersion)
  124. matched = TRUE;
  125. break;
  126. case VERSION_GREATER_THAN_EQUAL:
  127. if(osver.dwMajorVersion > majorVersion ||
  128. (osver.dwMajorVersion == majorVersion &&
  129. osver.dwMinorVersion >= minorVersion))
  130. matched = TRUE;
  131. break;
  132. case VERSION_GREATER_THAN:
  133. if(osver.dwMajorVersion > majorVersion ||
  134. (osver.dwMajorVersion == majorVersion &&
  135. osver.dwMinorVersion > minorVersion))
  136. matched = TRUE;
  137. break;
  138. }
  139. /* Verify the platform identifier (if necessary) */
  140. if(matched) {
  141. switch(platform) {
  142. case PLATFORM_WINDOWS:
  143. if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
  144. matched = FALSE;
  145. break;
  146. case PLATFORM_WINNT:
  147. if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
  148. matched = FALSE;
  149. default: /* like platform == PLATFORM_DONT_CARE */
  150. break;
  151. }
  152. }
  153. }
  154. #else
  155. ULONGLONG cm = 0;
  156. OSVERSIONINFOEX osver;
  157. BYTE majorCondition;
  158. BYTE minorCondition;
  159. BYTE spMajorCondition;
  160. BYTE spMinorCondition;
  161. switch(condition) {
  162. case VERSION_LESS_THAN:
  163. majorCondition = VER_LESS;
  164. minorCondition = VER_LESS;
  165. spMajorCondition = VER_LESS_EQUAL;
  166. spMinorCondition = VER_LESS_EQUAL;
  167. break;
  168. case VERSION_LESS_THAN_EQUAL:
  169. majorCondition = VER_LESS_EQUAL;
  170. minorCondition = VER_LESS_EQUAL;
  171. spMajorCondition = VER_LESS_EQUAL;
  172. spMinorCondition = VER_LESS_EQUAL;
  173. break;
  174. case VERSION_EQUAL:
  175. majorCondition = VER_EQUAL;
  176. minorCondition = VER_EQUAL;
  177. spMajorCondition = VER_GREATER_EQUAL;
  178. spMinorCondition = VER_GREATER_EQUAL;
  179. break;
  180. case VERSION_GREATER_THAN_EQUAL:
  181. majorCondition = VER_GREATER_EQUAL;
  182. minorCondition = VER_GREATER_EQUAL;
  183. spMajorCondition = VER_GREATER_EQUAL;
  184. spMinorCondition = VER_GREATER_EQUAL;
  185. break;
  186. case VERSION_GREATER_THAN:
  187. majorCondition = VER_GREATER;
  188. minorCondition = VER_GREATER;
  189. spMajorCondition = VER_GREATER_EQUAL;
  190. spMinorCondition = VER_GREATER_EQUAL;
  191. break;
  192. default:
  193. return FALSE;
  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. cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition);
  204. cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition);
  205. cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition);
  206. cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition);
  207. if(platform != PLATFORM_DONT_CARE)
  208. cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
  209. if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
  210. VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
  211. cm))
  212. matched = TRUE;
  213. #endif
  214. return matched;
  215. }
  216. #if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \
  217. defined(USE_WINSOCK))
  218. /*
  219. * Curl_load_library()
  220. *
  221. * This is used to dynamically load DLLs using the most secure method available
  222. * for the version of Windows that we are running on.
  223. *
  224. * Parameters:
  225. *
  226. * filename [in] - The filename or full path of the DLL to load. If only the
  227. * filename is passed then the DLL will be loaded from the
  228. * Windows system directory.
  229. *
  230. * Returns the handle of the module on success; otherwise NULL.
  231. */
  232. HMODULE Curl_load_library(LPCTSTR filename)
  233. {
  234. HMODULE hModule = NULL;
  235. LOADLIBRARYEX_FN pLoadLibraryEx = NULL;
  236. /* Get a handle to kernel32 so we can access it's functions at runtime */
  237. HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32"));
  238. if(!hKernel32)
  239. return NULL;
  240. /* Attempt to find LoadLibraryEx() which is only available on Windows 2000
  241. and above */
  242. pLoadLibraryEx =
  243. CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN,
  244. (GetProcAddress(hKernel32, LOADLIBARYEX)));
  245. /* Detect if there's already a path in the filename and load the library if
  246. there is. Note: Both back slashes and forward slashes have been supported
  247. since the earlier days of DOS at an API level although they are not
  248. supported by command prompt */
  249. if(_tcspbrk(filename, TEXT("\\/"))) {
  250. /** !checksrc! disable BANNEDFUNC 1 **/
  251. hModule = pLoadLibraryEx ?
  252. pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
  253. LoadLibrary(filename);
  254. }
  255. /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
  256. supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
  257. Server 2008 R2 with this patch or natively on Windows 8 and above */
  258. else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
  259. /* Load the DLL from the Windows system directory */
  260. hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
  261. }
  262. else {
  263. /* Attempt to get the Windows system path */
  264. UINT systemdirlen = GetSystemDirectory(NULL, 0);
  265. if(systemdirlen) {
  266. /* Allocate space for the full DLL path (Room for the null terminator
  267. is included in systemdirlen) */
  268. size_t filenamelen = _tcslen(filename);
  269. TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen));
  270. if(path && GetSystemDirectory(path, systemdirlen)) {
  271. /* Calculate the full DLL path */
  272. _tcscpy(path + _tcslen(path), TEXT("\\"));
  273. _tcscpy(path + _tcslen(path), filename);
  274. /* Load the DLL from the Windows system directory */
  275. /** !checksrc! disable BANNEDFUNC 1 **/
  276. hModule = pLoadLibraryEx ?
  277. pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
  278. LoadLibrary(path);
  279. }
  280. free(path);
  281. }
  282. }
  283. return hModule;
  284. }
  285. #endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */
  286. #endif /* WIN32 */