113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci#include "tool_setup.h" 2513498266Sopenharmony_ci 2613498266Sopenharmony_ci#if defined(_WIN32) || defined(MSDOS) 2713498266Sopenharmony_ci 2813498266Sopenharmony_ci#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) 2913498266Sopenharmony_ci# include <libgen.h> 3013498266Sopenharmony_ci#endif 3113498266Sopenharmony_ci 3213498266Sopenharmony_ci#ifdef _WIN32 3313498266Sopenharmony_ci# include <stdlib.h> 3413498266Sopenharmony_ci# include <tlhelp32.h> 3513498266Sopenharmony_ci# include "tool_cfgable.h" 3613498266Sopenharmony_ci# include "tool_libinfo.h" 3713498266Sopenharmony_ci#endif 3813498266Sopenharmony_ci 3913498266Sopenharmony_ci#include "tool_bname.h" 4013498266Sopenharmony_ci#include "tool_doswin.h" 4113498266Sopenharmony_ci 4213498266Sopenharmony_ci#include "curlx.h" 4313498266Sopenharmony_ci#include "memdebug.h" /* keep this as LAST include */ 4413498266Sopenharmony_ci 4513498266Sopenharmony_ci#ifdef _WIN32 4613498266Sopenharmony_ci# undef PATH_MAX 4713498266Sopenharmony_ci# define PATH_MAX MAX_PATH 4813498266Sopenharmony_ci#endif 4913498266Sopenharmony_ci 5013498266Sopenharmony_ci#ifndef S_ISCHR 5113498266Sopenharmony_ci# ifdef S_IFCHR 5213498266Sopenharmony_ci# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) 5313498266Sopenharmony_ci# else 5413498266Sopenharmony_ci# define S_ISCHR(m) (0) /* cannot tell if file is a device */ 5513498266Sopenharmony_ci# endif 5613498266Sopenharmony_ci#endif 5713498266Sopenharmony_ci 5813498266Sopenharmony_ci#ifdef _WIN32 5913498266Sopenharmony_ci# define _use_lfn(f) (1) /* long file names always available */ 6013498266Sopenharmony_ci#elif !defined(__DJGPP__) || (__DJGPP__ < 2) /* DJGPP 2.0 has _use_lfn() */ 6113498266Sopenharmony_ci# define _use_lfn(f) (0) /* long file names never available */ 6213498266Sopenharmony_ci#elif defined(__DJGPP__) 6313498266Sopenharmony_ci# include <fcntl.h> /* _use_lfn(f) prototype */ 6413498266Sopenharmony_ci#endif 6513498266Sopenharmony_ci 6613498266Sopenharmony_ci#ifndef UNITTESTS 6713498266Sopenharmony_cistatic SANITIZEcode truncate_dryrun(const char *path, 6813498266Sopenharmony_ci const size_t truncate_pos); 6913498266Sopenharmony_ci#ifdef MSDOS 7013498266Sopenharmony_cistatic SANITIZEcode msdosify(char **const sanitized, const char *file_name, 7113498266Sopenharmony_ci int flags); 7213498266Sopenharmony_ci#endif 7313498266Sopenharmony_cistatic SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized, 7413498266Sopenharmony_ci const char *file_name, 7513498266Sopenharmony_ci int flags); 7613498266Sopenharmony_ci#endif /* !UNITTESTS (static declarations used if no unit tests) */ 7713498266Sopenharmony_ci 7813498266Sopenharmony_ci 7913498266Sopenharmony_ci/* 8013498266Sopenharmony_ciSanitize a file or path name. 8113498266Sopenharmony_ci 8213498266Sopenharmony_ciAll banned characters are replaced by underscores, for example: 8313498266Sopenharmony_cif?*foo => f__foo 8413498266Sopenharmony_cif:foo::$DATA => f_foo__$DATA 8513498266Sopenharmony_cif:\foo:bar => f__foo_bar 8613498266Sopenharmony_cif:\foo:bar => f:\foo:bar (flag SANITIZE_ALLOW_PATH) 8713498266Sopenharmony_ci 8813498266Sopenharmony_ciThis function was implemented according to the guidelines in 'Naming Files, 8913498266Sopenharmony_ciPaths, and Namespaces' section 'Naming Conventions'. 9013498266Sopenharmony_cihttps://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx 9113498266Sopenharmony_ci 9213498266Sopenharmony_ciFlags 9313498266Sopenharmony_ci----- 9413498266Sopenharmony_ciSANITIZE_ALLOW_COLONS: Allow colons. 9513498266Sopenharmony_ciWithout this flag colons are sanitized. 9613498266Sopenharmony_ci 9713498266Sopenharmony_ciSANITIZE_ALLOW_PATH: Allow path separators and colons. 9813498266Sopenharmony_ciWithout this flag path separators and colons are sanitized. 9913498266Sopenharmony_ci 10013498266Sopenharmony_ciSANITIZE_ALLOW_RESERVED: Allow reserved device names. 10113498266Sopenharmony_ciWithout this flag a reserved device name is renamed (COM1 => _COM1) unless it's 10213498266Sopenharmony_ciin a UNC prefixed path. 10313498266Sopenharmony_ci 10413498266Sopenharmony_ciSANITIZE_ALLOW_TRUNCATE: Allow truncating a long filename. 10513498266Sopenharmony_ciWithout this flag if the sanitized filename or path will be too long an error 10613498266Sopenharmony_cioccurs. With this flag the filename --and not any other parts of the path-- may 10713498266Sopenharmony_cibe truncated to at least a single character. A filename followed by an 10813498266Sopenharmony_cialternate data stream (ADS) cannot be truncated in any case. 10913498266Sopenharmony_ci 11013498266Sopenharmony_ciSuccess: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name. 11113498266Sopenharmony_ciFailure: (!= SANITIZE_ERR_OK) *sanitized is NULL. 11213498266Sopenharmony_ci*/ 11313498266Sopenharmony_ciSANITIZEcode sanitize_file_name(char **const sanitized, const char *file_name, 11413498266Sopenharmony_ci int flags) 11513498266Sopenharmony_ci{ 11613498266Sopenharmony_ci char *p, *target; 11713498266Sopenharmony_ci size_t len; 11813498266Sopenharmony_ci SANITIZEcode sc; 11913498266Sopenharmony_ci size_t max_sanitized_len; 12013498266Sopenharmony_ci 12113498266Sopenharmony_ci if(!sanitized) 12213498266Sopenharmony_ci return SANITIZE_ERR_BAD_ARGUMENT; 12313498266Sopenharmony_ci 12413498266Sopenharmony_ci *sanitized = NULL; 12513498266Sopenharmony_ci 12613498266Sopenharmony_ci if(!file_name) 12713498266Sopenharmony_ci return SANITIZE_ERR_BAD_ARGUMENT; 12813498266Sopenharmony_ci 12913498266Sopenharmony_ci if((flags & SANITIZE_ALLOW_PATH)) { 13013498266Sopenharmony_ci#ifndef MSDOS 13113498266Sopenharmony_ci if(file_name[0] == '\\' && file_name[1] == '\\') 13213498266Sopenharmony_ci /* UNC prefixed path \\ (eg \\?\C:\foo) */ 13313498266Sopenharmony_ci max_sanitized_len = 32767-1; 13413498266Sopenharmony_ci else 13513498266Sopenharmony_ci#endif 13613498266Sopenharmony_ci max_sanitized_len = PATH_MAX-1; 13713498266Sopenharmony_ci } 13813498266Sopenharmony_ci else 13913498266Sopenharmony_ci /* The maximum length of a filename. 14013498266Sopenharmony_ci FILENAME_MAX is often the same as PATH_MAX, in other words it is 260 and 14113498266Sopenharmony_ci does not discount the path information therefore we shouldn't use it. */ 14213498266Sopenharmony_ci max_sanitized_len = (PATH_MAX-1 > 255) ? 255 : PATH_MAX-1; 14313498266Sopenharmony_ci 14413498266Sopenharmony_ci len = strlen(file_name); 14513498266Sopenharmony_ci if(len > max_sanitized_len) { 14613498266Sopenharmony_ci if(!(flags & SANITIZE_ALLOW_TRUNCATE) || 14713498266Sopenharmony_ci truncate_dryrun(file_name, max_sanitized_len)) 14813498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 14913498266Sopenharmony_ci 15013498266Sopenharmony_ci len = max_sanitized_len; 15113498266Sopenharmony_ci } 15213498266Sopenharmony_ci 15313498266Sopenharmony_ci target = malloc(len + 1); 15413498266Sopenharmony_ci if(!target) 15513498266Sopenharmony_ci return SANITIZE_ERR_OUT_OF_MEMORY; 15613498266Sopenharmony_ci 15713498266Sopenharmony_ci strncpy(target, file_name, len); 15813498266Sopenharmony_ci target[len] = '\0'; 15913498266Sopenharmony_ci 16013498266Sopenharmony_ci#ifndef MSDOS 16113498266Sopenharmony_ci if((flags & SANITIZE_ALLOW_PATH) && !strncmp(target, "\\\\?\\", 4)) 16213498266Sopenharmony_ci /* Skip the literal path prefix \\?\ */ 16313498266Sopenharmony_ci p = target + 4; 16413498266Sopenharmony_ci else 16513498266Sopenharmony_ci#endif 16613498266Sopenharmony_ci p = target; 16713498266Sopenharmony_ci 16813498266Sopenharmony_ci /* replace control characters and other banned characters */ 16913498266Sopenharmony_ci for(; *p; ++p) { 17013498266Sopenharmony_ci const char *banned; 17113498266Sopenharmony_ci 17213498266Sopenharmony_ci if((1 <= *p && *p <= 31) || 17313498266Sopenharmony_ci (!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *p == ':') || 17413498266Sopenharmony_ci (!(flags & SANITIZE_ALLOW_PATH) && (*p == '/' || *p == '\\'))) { 17513498266Sopenharmony_ci *p = '_'; 17613498266Sopenharmony_ci continue; 17713498266Sopenharmony_ci } 17813498266Sopenharmony_ci 17913498266Sopenharmony_ci for(banned = "|<>\"?*"; *banned; ++banned) { 18013498266Sopenharmony_ci if(*p == *banned) { 18113498266Sopenharmony_ci *p = '_'; 18213498266Sopenharmony_ci break; 18313498266Sopenharmony_ci } 18413498266Sopenharmony_ci } 18513498266Sopenharmony_ci } 18613498266Sopenharmony_ci 18713498266Sopenharmony_ci /* remove trailing spaces and periods if not allowing paths */ 18813498266Sopenharmony_ci if(!(flags & SANITIZE_ALLOW_PATH) && len) { 18913498266Sopenharmony_ci char *clip = NULL; 19013498266Sopenharmony_ci 19113498266Sopenharmony_ci p = &target[len]; 19213498266Sopenharmony_ci do { 19313498266Sopenharmony_ci --p; 19413498266Sopenharmony_ci if(*p != ' ' && *p != '.') 19513498266Sopenharmony_ci break; 19613498266Sopenharmony_ci clip = p; 19713498266Sopenharmony_ci } while(p != target); 19813498266Sopenharmony_ci 19913498266Sopenharmony_ci if(clip) { 20013498266Sopenharmony_ci *clip = '\0'; 20113498266Sopenharmony_ci len = clip - target; 20213498266Sopenharmony_ci } 20313498266Sopenharmony_ci } 20413498266Sopenharmony_ci 20513498266Sopenharmony_ci#ifdef MSDOS 20613498266Sopenharmony_ci sc = msdosify(&p, target, flags); 20713498266Sopenharmony_ci free(target); 20813498266Sopenharmony_ci if(sc) 20913498266Sopenharmony_ci return sc; 21013498266Sopenharmony_ci target = p; 21113498266Sopenharmony_ci len = strlen(target); 21213498266Sopenharmony_ci 21313498266Sopenharmony_ci if(len > max_sanitized_len) { 21413498266Sopenharmony_ci free(target); 21513498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 21613498266Sopenharmony_ci } 21713498266Sopenharmony_ci#endif 21813498266Sopenharmony_ci 21913498266Sopenharmony_ci if(!(flags & SANITIZE_ALLOW_RESERVED)) { 22013498266Sopenharmony_ci sc = rename_if_reserved_dos_device_name(&p, target, flags); 22113498266Sopenharmony_ci free(target); 22213498266Sopenharmony_ci if(sc) 22313498266Sopenharmony_ci return sc; 22413498266Sopenharmony_ci target = p; 22513498266Sopenharmony_ci len = strlen(target); 22613498266Sopenharmony_ci 22713498266Sopenharmony_ci if(len > max_sanitized_len) { 22813498266Sopenharmony_ci free(target); 22913498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 23013498266Sopenharmony_ci } 23113498266Sopenharmony_ci } 23213498266Sopenharmony_ci 23313498266Sopenharmony_ci *sanitized = target; 23413498266Sopenharmony_ci return SANITIZE_ERR_OK; 23513498266Sopenharmony_ci} 23613498266Sopenharmony_ci 23713498266Sopenharmony_ci 23813498266Sopenharmony_ci/* 23913498266Sopenharmony_ciTest if truncating a path to a file will leave at least a single character in 24013498266Sopenharmony_cithe filename. Filenames suffixed by an alternate data stream can't be 24113498266Sopenharmony_citruncated. This performs a dry run, nothing is modified. 24213498266Sopenharmony_ci 24313498266Sopenharmony_ciGood truncate_pos 9: C:\foo\bar => C:\foo\ba 24413498266Sopenharmony_ciGood truncate_pos 6: C:\foo => C:\foo 24513498266Sopenharmony_ciGood truncate_pos 5: C:\foo => C:\fo 24613498266Sopenharmony_ciBad* truncate_pos 5: C:foo => C:foo 24713498266Sopenharmony_ciBad truncate_pos 5: C:\foo:ads => C:\fo 24813498266Sopenharmony_ciBad truncate_pos 9: C:\foo:ads => C:\foo:ad 24913498266Sopenharmony_ciBad truncate_pos 5: C:\foo\bar => C:\fo 25013498266Sopenharmony_ciBad truncate_pos 5: C:\foo\ => C:\fo 25113498266Sopenharmony_ciBad truncate_pos 7: C:\foo\ => C:\foo\ 25213498266Sopenharmony_ciError truncate_pos 7: C:\foo => (pos out of range) 25313498266Sopenharmony_ciBad truncate_pos 1: C:\foo\ => C 25413498266Sopenharmony_ci 25513498266Sopenharmony_ci* C:foo is ambiguous, C could end up being a drive or file therefore something 25613498266Sopenharmony_ci like C:superlongfilename can't be truncated. 25713498266Sopenharmony_ci 25813498266Sopenharmony_ciReturns 25913498266Sopenharmony_ciSANITIZE_ERR_OK: Good -- 'path' can be truncated 26013498266Sopenharmony_ciSANITIZE_ERR_INVALID_PATH: Bad -- 'path' cannot be truncated 26113498266Sopenharmony_ci!= SANITIZE_ERR_OK && != SANITIZE_ERR_INVALID_PATH: Error 26213498266Sopenharmony_ci*/ 26313498266Sopenharmony_ciSANITIZEcode truncate_dryrun(const char *path, const size_t truncate_pos) 26413498266Sopenharmony_ci{ 26513498266Sopenharmony_ci size_t len; 26613498266Sopenharmony_ci 26713498266Sopenharmony_ci if(!path) 26813498266Sopenharmony_ci return SANITIZE_ERR_BAD_ARGUMENT; 26913498266Sopenharmony_ci 27013498266Sopenharmony_ci len = strlen(path); 27113498266Sopenharmony_ci 27213498266Sopenharmony_ci if(truncate_pos > len) 27313498266Sopenharmony_ci return SANITIZE_ERR_BAD_ARGUMENT; 27413498266Sopenharmony_ci 27513498266Sopenharmony_ci if(!len || !truncate_pos) 27613498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 27713498266Sopenharmony_ci 27813498266Sopenharmony_ci if(strpbrk(&path[truncate_pos - 1], "\\/:")) 27913498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 28013498266Sopenharmony_ci 28113498266Sopenharmony_ci /* C:\foo can be truncated but C:\foo:ads can't */ 28213498266Sopenharmony_ci if(truncate_pos > 1) { 28313498266Sopenharmony_ci const char *p = &path[truncate_pos - 1]; 28413498266Sopenharmony_ci do { 28513498266Sopenharmony_ci --p; 28613498266Sopenharmony_ci if(*p == ':') 28713498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 28813498266Sopenharmony_ci } while(p != path && *p != '\\' && *p != '/'); 28913498266Sopenharmony_ci } 29013498266Sopenharmony_ci 29113498266Sopenharmony_ci return SANITIZE_ERR_OK; 29213498266Sopenharmony_ci} 29313498266Sopenharmony_ci 29413498266Sopenharmony_ci/* The functions msdosify, rename_if_dos_device_name and __crt0_glob_function 29513498266Sopenharmony_ci * were taken with modification from the DJGPP port of tar 1.12. They use 29613498266Sopenharmony_ci * algorithms originally from DJTAR. 29713498266Sopenharmony_ci */ 29813498266Sopenharmony_ci 29913498266Sopenharmony_ci/* 30013498266Sopenharmony_ciExtra sanitization MSDOS for file_name. 30113498266Sopenharmony_ci 30213498266Sopenharmony_ciThis is a supporting function for sanitize_file_name. 30313498266Sopenharmony_ci 30413498266Sopenharmony_ciWarning: This is an MSDOS legacy function and was purposely written in a way 30513498266Sopenharmony_cithat some path information may pass through. For example drive letter names 30613498266Sopenharmony_ci(C:, D:, etc) are allowed to pass through. For sanitizing a filename use 30713498266Sopenharmony_cisanitize_file_name. 30813498266Sopenharmony_ci 30913498266Sopenharmony_ciSuccess: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name. 31013498266Sopenharmony_ciFailure: (!= SANITIZE_ERR_OK) *sanitized is NULL. 31113498266Sopenharmony_ci*/ 31213498266Sopenharmony_ci#if defined(MSDOS) || defined(UNITTESTS) 31313498266Sopenharmony_ciSANITIZEcode msdosify(char **const sanitized, const char *file_name, 31413498266Sopenharmony_ci int flags) 31513498266Sopenharmony_ci{ 31613498266Sopenharmony_ci char dos_name[PATH_MAX]; 31713498266Sopenharmony_ci static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */ 31813498266Sopenharmony_ci "|<>/\\\":?*"; /* illegal in DOS & W95 */ 31913498266Sopenharmony_ci static const char *illegal_chars_w95 = &illegal_chars_dos[8]; 32013498266Sopenharmony_ci int idx, dot_idx; 32113498266Sopenharmony_ci const char *s = file_name; 32213498266Sopenharmony_ci char *d = dos_name; 32313498266Sopenharmony_ci const char *const dlimit = dos_name + sizeof(dos_name) - 1; 32413498266Sopenharmony_ci const char *illegal_aliens = illegal_chars_dos; 32513498266Sopenharmony_ci size_t len = sizeof(illegal_chars_dos) - 1; 32613498266Sopenharmony_ci 32713498266Sopenharmony_ci if(!sanitized) 32813498266Sopenharmony_ci return SANITIZE_ERR_BAD_ARGUMENT; 32913498266Sopenharmony_ci 33013498266Sopenharmony_ci *sanitized = NULL; 33113498266Sopenharmony_ci 33213498266Sopenharmony_ci if(!file_name) 33313498266Sopenharmony_ci return SANITIZE_ERR_BAD_ARGUMENT; 33413498266Sopenharmony_ci 33513498266Sopenharmony_ci if(strlen(file_name) > PATH_MAX-1 && 33613498266Sopenharmony_ci (!(flags & SANITIZE_ALLOW_TRUNCATE) || 33713498266Sopenharmony_ci truncate_dryrun(file_name, PATH_MAX-1))) 33813498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 33913498266Sopenharmony_ci 34013498266Sopenharmony_ci /* Support for Windows 9X VFAT systems, when available. */ 34113498266Sopenharmony_ci if(_use_lfn(file_name)) { 34213498266Sopenharmony_ci illegal_aliens = illegal_chars_w95; 34313498266Sopenharmony_ci len -= (illegal_chars_w95 - illegal_chars_dos); 34413498266Sopenharmony_ci } 34513498266Sopenharmony_ci 34613498266Sopenharmony_ci /* Get past the drive letter, if any. */ 34713498266Sopenharmony_ci if(s[0] >= 'A' && s[0] <= 'z' && s[1] == ':') { 34813498266Sopenharmony_ci *d++ = *s++; 34913498266Sopenharmony_ci *d = ((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) ? ':' : '_'; 35013498266Sopenharmony_ci ++d; ++s; 35113498266Sopenharmony_ci } 35213498266Sopenharmony_ci 35313498266Sopenharmony_ci for(idx = 0, dot_idx = -1; *s && d < dlimit; s++, d++) { 35413498266Sopenharmony_ci if(memchr(illegal_aliens, *s, len)) { 35513498266Sopenharmony_ci 35613498266Sopenharmony_ci if((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *s == ':') 35713498266Sopenharmony_ci *d = ':'; 35813498266Sopenharmony_ci else if((flags & SANITIZE_ALLOW_PATH) && (*s == '/' || *s == '\\')) 35913498266Sopenharmony_ci *d = *s; 36013498266Sopenharmony_ci /* Dots are special: DOS doesn't allow them as the leading character, 36113498266Sopenharmony_ci and a file name cannot have more than a single dot. We leave the 36213498266Sopenharmony_ci first non-leading dot alone, unless it comes too close to the 36313498266Sopenharmony_ci beginning of the name: we want sh.lex.c to become sh_lex.c, not 36413498266Sopenharmony_ci sh.lex-c. */ 36513498266Sopenharmony_ci else if(*s == '.') { 36613498266Sopenharmony_ci if((flags & SANITIZE_ALLOW_PATH) && idx == 0 && 36713498266Sopenharmony_ci (s[1] == '/' || s[1] == '\\' || 36813498266Sopenharmony_ci (s[1] == '.' && (s[2] == '/' || s[2] == '\\')))) { 36913498266Sopenharmony_ci /* Copy "./" and "../" verbatim. */ 37013498266Sopenharmony_ci *d++ = *s++; 37113498266Sopenharmony_ci if(d == dlimit) 37213498266Sopenharmony_ci break; 37313498266Sopenharmony_ci if(*s == '.') { 37413498266Sopenharmony_ci *d++ = *s++; 37513498266Sopenharmony_ci if(d == dlimit) 37613498266Sopenharmony_ci break; 37713498266Sopenharmony_ci } 37813498266Sopenharmony_ci *d = *s; 37913498266Sopenharmony_ci } 38013498266Sopenharmony_ci else if(idx == 0) 38113498266Sopenharmony_ci *d = '_'; 38213498266Sopenharmony_ci else if(dot_idx >= 0) { 38313498266Sopenharmony_ci if(dot_idx < 5) { /* 5 is a heuristic ad-hoc'ery */ 38413498266Sopenharmony_ci d[dot_idx - idx] = '_'; /* replace previous dot */ 38513498266Sopenharmony_ci *d = '.'; 38613498266Sopenharmony_ci } 38713498266Sopenharmony_ci else 38813498266Sopenharmony_ci *d = '-'; 38913498266Sopenharmony_ci } 39013498266Sopenharmony_ci else 39113498266Sopenharmony_ci *d = '.'; 39213498266Sopenharmony_ci 39313498266Sopenharmony_ci if(*s == '.') 39413498266Sopenharmony_ci dot_idx = idx; 39513498266Sopenharmony_ci } 39613498266Sopenharmony_ci else if(*s == '+' && s[1] == '+') { 39713498266Sopenharmony_ci if(idx - 2 == dot_idx) { /* .c++, .h++ etc. */ 39813498266Sopenharmony_ci *d++ = 'x'; 39913498266Sopenharmony_ci if(d == dlimit) 40013498266Sopenharmony_ci break; 40113498266Sopenharmony_ci *d = 'x'; 40213498266Sopenharmony_ci } 40313498266Sopenharmony_ci else { 40413498266Sopenharmony_ci /* libg++ etc. */ 40513498266Sopenharmony_ci if(dlimit - d < 4) { 40613498266Sopenharmony_ci *d++ = 'x'; 40713498266Sopenharmony_ci if(d == dlimit) 40813498266Sopenharmony_ci break; 40913498266Sopenharmony_ci *d = 'x'; 41013498266Sopenharmony_ci } 41113498266Sopenharmony_ci else { 41213498266Sopenharmony_ci memcpy(d, "plus", 4); 41313498266Sopenharmony_ci d += 3; 41413498266Sopenharmony_ci } 41513498266Sopenharmony_ci } 41613498266Sopenharmony_ci s++; 41713498266Sopenharmony_ci idx++; 41813498266Sopenharmony_ci } 41913498266Sopenharmony_ci else 42013498266Sopenharmony_ci *d = '_'; 42113498266Sopenharmony_ci } 42213498266Sopenharmony_ci else 42313498266Sopenharmony_ci *d = *s; 42413498266Sopenharmony_ci if(*s == '/' || *s == '\\') { 42513498266Sopenharmony_ci idx = 0; 42613498266Sopenharmony_ci dot_idx = -1; 42713498266Sopenharmony_ci } 42813498266Sopenharmony_ci else 42913498266Sopenharmony_ci idx++; 43013498266Sopenharmony_ci } 43113498266Sopenharmony_ci *d = '\0'; 43213498266Sopenharmony_ci 43313498266Sopenharmony_ci if(*s) { 43413498266Sopenharmony_ci /* dos_name is truncated, check that truncation requirements are met, 43513498266Sopenharmony_ci specifically truncating a filename suffixed by an alternate data stream 43613498266Sopenharmony_ci or truncating the entire filename is not allowed. */ 43713498266Sopenharmony_ci if(!(flags & SANITIZE_ALLOW_TRUNCATE) || strpbrk(s, "\\/:") || 43813498266Sopenharmony_ci truncate_dryrun(dos_name, d - dos_name)) 43913498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 44013498266Sopenharmony_ci } 44113498266Sopenharmony_ci 44213498266Sopenharmony_ci *sanitized = strdup(dos_name); 44313498266Sopenharmony_ci return (*sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY); 44413498266Sopenharmony_ci} 44513498266Sopenharmony_ci#endif /* MSDOS || UNITTESTS */ 44613498266Sopenharmony_ci 44713498266Sopenharmony_ci/* 44813498266Sopenharmony_ciRename file_name if it's a reserved dos device name. 44913498266Sopenharmony_ci 45013498266Sopenharmony_ciThis is a supporting function for sanitize_file_name. 45113498266Sopenharmony_ci 45213498266Sopenharmony_ciWarning: This is an MSDOS legacy function and was purposely written in a way 45313498266Sopenharmony_cithat some path information may pass through. For example drive letter names 45413498266Sopenharmony_ci(C:, D:, etc) are allowed to pass through. For sanitizing a filename use 45513498266Sopenharmony_cisanitize_file_name. 45613498266Sopenharmony_ci 45713498266Sopenharmony_ciSuccess: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name. 45813498266Sopenharmony_ciFailure: (!= SANITIZE_ERR_OK) *sanitized is NULL. 45913498266Sopenharmony_ci*/ 46013498266Sopenharmony_ciSANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized, 46113498266Sopenharmony_ci const char *file_name, 46213498266Sopenharmony_ci int flags) 46313498266Sopenharmony_ci{ 46413498266Sopenharmony_ci /* We could have a file whose name is a device on MS-DOS. Trying to 46513498266Sopenharmony_ci * retrieve such a file would fail at best and wedge us at worst. We need 46613498266Sopenharmony_ci * to rename such files. */ 46713498266Sopenharmony_ci char *p, *base; 46813498266Sopenharmony_ci char fname[PATH_MAX]; 46913498266Sopenharmony_ci#ifdef MSDOS 47013498266Sopenharmony_ci struct_stat st_buf; 47113498266Sopenharmony_ci#endif 47213498266Sopenharmony_ci 47313498266Sopenharmony_ci if(!sanitized) 47413498266Sopenharmony_ci return SANITIZE_ERR_BAD_ARGUMENT; 47513498266Sopenharmony_ci 47613498266Sopenharmony_ci *sanitized = NULL; 47713498266Sopenharmony_ci 47813498266Sopenharmony_ci if(!file_name) 47913498266Sopenharmony_ci return SANITIZE_ERR_BAD_ARGUMENT; 48013498266Sopenharmony_ci 48113498266Sopenharmony_ci /* Ignore UNC prefixed paths, they are allowed to contain a reserved name. */ 48213498266Sopenharmony_ci#ifndef MSDOS 48313498266Sopenharmony_ci if((flags & SANITIZE_ALLOW_PATH) && 48413498266Sopenharmony_ci file_name[0] == '\\' && file_name[1] == '\\') { 48513498266Sopenharmony_ci size_t len = strlen(file_name); 48613498266Sopenharmony_ci *sanitized = malloc(len + 1); 48713498266Sopenharmony_ci if(!*sanitized) 48813498266Sopenharmony_ci return SANITIZE_ERR_OUT_OF_MEMORY; 48913498266Sopenharmony_ci strncpy(*sanitized, file_name, len + 1); 49013498266Sopenharmony_ci return SANITIZE_ERR_OK; 49113498266Sopenharmony_ci } 49213498266Sopenharmony_ci#endif 49313498266Sopenharmony_ci 49413498266Sopenharmony_ci if(strlen(file_name) > PATH_MAX-1 && 49513498266Sopenharmony_ci (!(flags & SANITIZE_ALLOW_TRUNCATE) || 49613498266Sopenharmony_ci truncate_dryrun(file_name, PATH_MAX-1))) 49713498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 49813498266Sopenharmony_ci 49913498266Sopenharmony_ci strncpy(fname, file_name, PATH_MAX-1); 50013498266Sopenharmony_ci fname[PATH_MAX-1] = '\0'; 50113498266Sopenharmony_ci base = basename(fname); 50213498266Sopenharmony_ci 50313498266Sopenharmony_ci /* Rename reserved device names that are known to be accessible without \\.\ 50413498266Sopenharmony_ci Examples: CON => _CON, CON.EXT => CON_EXT, CON:ADS => CON_ADS 50513498266Sopenharmony_ci https://support.microsoft.com/en-us/kb/74496 50613498266Sopenharmony_ci https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx 50713498266Sopenharmony_ci */ 50813498266Sopenharmony_ci for(p = fname; p; p = (p == fname && fname != base ? base : NULL)) { 50913498266Sopenharmony_ci size_t p_len; 51013498266Sopenharmony_ci int x = (curl_strnequal(p, "CON", 3) || 51113498266Sopenharmony_ci curl_strnequal(p, "PRN", 3) || 51213498266Sopenharmony_ci curl_strnequal(p, "AUX", 3) || 51313498266Sopenharmony_ci curl_strnequal(p, "NUL", 3)) ? 3 : 51413498266Sopenharmony_ci (curl_strnequal(p, "CLOCK$", 6)) ? 6 : 51513498266Sopenharmony_ci (curl_strnequal(p, "COM", 3) || curl_strnequal(p, "LPT", 3)) ? 51613498266Sopenharmony_ci (('1' <= p[3] && p[3] <= '9') ? 4 : 3) : 0; 51713498266Sopenharmony_ci 51813498266Sopenharmony_ci if(!x) 51913498266Sopenharmony_ci continue; 52013498266Sopenharmony_ci 52113498266Sopenharmony_ci /* the devices may be accessible with an extension or ADS, for 52213498266Sopenharmony_ci example CON.AIR and 'CON . AIR' and CON:AIR access console */ 52313498266Sopenharmony_ci 52413498266Sopenharmony_ci for(; p[x] == ' '; ++x) 52513498266Sopenharmony_ci ; 52613498266Sopenharmony_ci 52713498266Sopenharmony_ci if(p[x] == '.') { 52813498266Sopenharmony_ci p[x] = '_'; 52913498266Sopenharmony_ci continue; 53013498266Sopenharmony_ci } 53113498266Sopenharmony_ci else if(p[x] == ':') { 53213498266Sopenharmony_ci if(!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) { 53313498266Sopenharmony_ci p[x] = '_'; 53413498266Sopenharmony_ci continue; 53513498266Sopenharmony_ci } 53613498266Sopenharmony_ci ++x; 53713498266Sopenharmony_ci } 53813498266Sopenharmony_ci else if(p[x]) /* no match */ 53913498266Sopenharmony_ci continue; 54013498266Sopenharmony_ci 54113498266Sopenharmony_ci /* p points to 'CON' or 'CON ' or 'CON:', etc */ 54213498266Sopenharmony_ci p_len = strlen(p); 54313498266Sopenharmony_ci 54413498266Sopenharmony_ci /* Prepend a '_' */ 54513498266Sopenharmony_ci if(strlen(fname) == PATH_MAX-1) { 54613498266Sopenharmony_ci --p_len; 54713498266Sopenharmony_ci if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(p, p_len)) 54813498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 54913498266Sopenharmony_ci p[p_len] = '\0'; 55013498266Sopenharmony_ci } 55113498266Sopenharmony_ci memmove(p + 1, p, p_len + 1); 55213498266Sopenharmony_ci p[0] = '_'; 55313498266Sopenharmony_ci ++p_len; 55413498266Sopenharmony_ci 55513498266Sopenharmony_ci /* if fname was just modified then the basename pointer must be updated */ 55613498266Sopenharmony_ci if(p == fname) 55713498266Sopenharmony_ci base = basename(fname); 55813498266Sopenharmony_ci } 55913498266Sopenharmony_ci 56013498266Sopenharmony_ci /* This is the legacy portion from rename_if_dos_device_name that checks for 56113498266Sopenharmony_ci reserved device names. It only works on MSDOS. On Windows XP the stat 56213498266Sopenharmony_ci check errors with EINVAL if the device name is reserved. On Windows 56313498266Sopenharmony_ci Vista/7/8 it sets mode S_IFREG (regular file or device). According to MSDN 56413498266Sopenharmony_ci stat doc the latter behavior is correct, but that doesn't help us identify 56513498266Sopenharmony_ci whether it's a reserved device name and not a regular file name. */ 56613498266Sopenharmony_ci#ifdef MSDOS 56713498266Sopenharmony_ci if(base && ((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) { 56813498266Sopenharmony_ci /* Prepend a '_' */ 56913498266Sopenharmony_ci size_t blen = strlen(base); 57013498266Sopenharmony_ci if(blen) { 57113498266Sopenharmony_ci if(strlen(fname) == PATH_MAX-1) { 57213498266Sopenharmony_ci --blen; 57313498266Sopenharmony_ci if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(base, blen)) 57413498266Sopenharmony_ci return SANITIZE_ERR_INVALID_PATH; 57513498266Sopenharmony_ci base[blen] = '\0'; 57613498266Sopenharmony_ci } 57713498266Sopenharmony_ci memmove(base + 1, base, blen + 1); 57813498266Sopenharmony_ci base[0] = '_'; 57913498266Sopenharmony_ci } 58013498266Sopenharmony_ci } 58113498266Sopenharmony_ci#endif 58213498266Sopenharmony_ci 58313498266Sopenharmony_ci *sanitized = strdup(fname); 58413498266Sopenharmony_ci return (*sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY); 58513498266Sopenharmony_ci} 58613498266Sopenharmony_ci 58713498266Sopenharmony_ci#if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__)) 58813498266Sopenharmony_ci 58913498266Sopenharmony_ci/* 59013498266Sopenharmony_ci * Disable program default argument globbing. We do it on our own. 59113498266Sopenharmony_ci */ 59213498266Sopenharmony_cichar **__crt0_glob_function(char *arg) 59313498266Sopenharmony_ci{ 59413498266Sopenharmony_ci (void)arg; 59513498266Sopenharmony_ci return (char **)0; 59613498266Sopenharmony_ci} 59713498266Sopenharmony_ci 59813498266Sopenharmony_ci#endif /* MSDOS && (__DJGPP__ || __GO32__) */ 59913498266Sopenharmony_ci 60013498266Sopenharmony_ci#ifdef _WIN32 60113498266Sopenharmony_ci 60213498266Sopenharmony_ci/* 60313498266Sopenharmony_ci * Function to find CACert bundle on a Win32 platform using SearchPath. 60413498266Sopenharmony_ci * (SearchPath is already declared via inclusions done in setup header file) 60513498266Sopenharmony_ci * (Use the ASCII version instead of the unicode one!) 60613498266Sopenharmony_ci * The order of the directories it searches is: 60713498266Sopenharmony_ci * 1. application's directory 60813498266Sopenharmony_ci * 2. current working directory 60913498266Sopenharmony_ci * 3. Windows System directory (e.g. C:\windows\system32) 61013498266Sopenharmony_ci * 4. Windows Directory (e.g. C:\windows) 61113498266Sopenharmony_ci * 5. all directories along %PATH% 61213498266Sopenharmony_ci * 61313498266Sopenharmony_ci * For WinXP and later search order actually depends on registry value: 61413498266Sopenharmony_ci * HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeProcessSearchMode 61513498266Sopenharmony_ci */ 61613498266Sopenharmony_ci 61713498266Sopenharmony_ciCURLcode FindWin32CACert(struct OperationConfig *config, 61813498266Sopenharmony_ci curl_sslbackend backend, 61913498266Sopenharmony_ci const TCHAR *bundle_file) 62013498266Sopenharmony_ci{ 62113498266Sopenharmony_ci CURLcode result = CURLE_OK; 62213498266Sopenharmony_ci 62313498266Sopenharmony_ci /* Search and set cert file only if libcurl supports SSL. 62413498266Sopenharmony_ci * 62513498266Sopenharmony_ci * If Schannel is the selected SSL backend then these locations are 62613498266Sopenharmony_ci * ignored. We allow setting CA location for schannel only when explicitly 62713498266Sopenharmony_ci * specified by the user via CURLOPT_CAINFO / --cacert. 62813498266Sopenharmony_ci */ 62913498266Sopenharmony_ci if(feature_ssl && backend != CURLSSLBACKEND_SCHANNEL) { 63013498266Sopenharmony_ci 63113498266Sopenharmony_ci DWORD res_len; 63213498266Sopenharmony_ci TCHAR buf[PATH_MAX]; 63313498266Sopenharmony_ci TCHAR *ptr = NULL; 63413498266Sopenharmony_ci 63513498266Sopenharmony_ci buf[0] = TEXT('\0'); 63613498266Sopenharmony_ci 63713498266Sopenharmony_ci res_len = SearchPath(NULL, bundle_file, NULL, PATH_MAX, buf, &ptr); 63813498266Sopenharmony_ci if(res_len > 0) { 63913498266Sopenharmony_ci char *mstr = curlx_convert_tchar_to_UTF8(buf); 64013498266Sopenharmony_ci Curl_safefree(config->cacert); 64113498266Sopenharmony_ci if(mstr) 64213498266Sopenharmony_ci config->cacert = strdup(mstr); 64313498266Sopenharmony_ci curlx_unicodefree(mstr); 64413498266Sopenharmony_ci if(!config->cacert) 64513498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 64613498266Sopenharmony_ci } 64713498266Sopenharmony_ci } 64813498266Sopenharmony_ci 64913498266Sopenharmony_ci return result; 65013498266Sopenharmony_ci} 65113498266Sopenharmony_ci 65213498266Sopenharmony_ci 65313498266Sopenharmony_ci/* Get a list of all loaded modules with full paths. 65413498266Sopenharmony_ci * Returns slist on success or NULL on error. 65513498266Sopenharmony_ci */ 65613498266Sopenharmony_cistruct curl_slist *GetLoadedModulePaths(void) 65713498266Sopenharmony_ci{ 65813498266Sopenharmony_ci HANDLE hnd = INVALID_HANDLE_VALUE; 65913498266Sopenharmony_ci MODULEENTRY32 mod = {0}; 66013498266Sopenharmony_ci struct curl_slist *slist = NULL; 66113498266Sopenharmony_ci 66213498266Sopenharmony_ci mod.dwSize = sizeof(MODULEENTRY32); 66313498266Sopenharmony_ci 66413498266Sopenharmony_ci do { 66513498266Sopenharmony_ci hnd = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); 66613498266Sopenharmony_ci } while(hnd == INVALID_HANDLE_VALUE && GetLastError() == ERROR_BAD_LENGTH); 66713498266Sopenharmony_ci 66813498266Sopenharmony_ci if(hnd == INVALID_HANDLE_VALUE) 66913498266Sopenharmony_ci goto error; 67013498266Sopenharmony_ci 67113498266Sopenharmony_ci if(!Module32First(hnd, &mod)) 67213498266Sopenharmony_ci goto error; 67313498266Sopenharmony_ci 67413498266Sopenharmony_ci do { 67513498266Sopenharmony_ci char *path; /* points to stack allocated buffer */ 67613498266Sopenharmony_ci struct curl_slist *temp; 67713498266Sopenharmony_ci 67813498266Sopenharmony_ci#ifdef UNICODE 67913498266Sopenharmony_ci /* sizeof(mod.szExePath) is the max total bytes of wchars. the max total 68013498266Sopenharmony_ci bytes of multibyte chars won't be more than twice that. */ 68113498266Sopenharmony_ci char buffer[sizeof(mod.szExePath) * 2]; 68213498266Sopenharmony_ci if(!WideCharToMultiByte(CP_ACP, 0, mod.szExePath, -1, 68313498266Sopenharmony_ci buffer, sizeof(buffer), NULL, NULL)) 68413498266Sopenharmony_ci goto error; 68513498266Sopenharmony_ci path = buffer; 68613498266Sopenharmony_ci#else 68713498266Sopenharmony_ci path = mod.szExePath; 68813498266Sopenharmony_ci#endif 68913498266Sopenharmony_ci temp = curl_slist_append(slist, path); 69013498266Sopenharmony_ci if(!temp) 69113498266Sopenharmony_ci goto error; 69213498266Sopenharmony_ci slist = temp; 69313498266Sopenharmony_ci } while(Module32Next(hnd, &mod)); 69413498266Sopenharmony_ci 69513498266Sopenharmony_ci goto cleanup; 69613498266Sopenharmony_ci 69713498266Sopenharmony_cierror: 69813498266Sopenharmony_ci curl_slist_free_all(slist); 69913498266Sopenharmony_ci slist = NULL; 70013498266Sopenharmony_cicleanup: 70113498266Sopenharmony_ci if(hnd != INVALID_HANDLE_VALUE) 70213498266Sopenharmony_ci CloseHandle(hnd); 70313498266Sopenharmony_ci return slist; 70413498266Sopenharmony_ci} 70513498266Sopenharmony_ci 70613498266Sopenharmony_ci/* The terminal settings to restore on exit */ 70713498266Sopenharmony_cistatic struct TerminalSettings { 70813498266Sopenharmony_ci HANDLE hStdOut; 70913498266Sopenharmony_ci DWORD dwOutputMode; 71013498266Sopenharmony_ci LONG valid; 71113498266Sopenharmony_ci} TerminalSettings; 71213498266Sopenharmony_ci 71313498266Sopenharmony_ci#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING 71413498266Sopenharmony_ci#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 71513498266Sopenharmony_ci#endif 71613498266Sopenharmony_ci 71713498266Sopenharmony_cibool tool_term_has_bold; 71813498266Sopenharmony_ci 71913498266Sopenharmony_cistatic void restore_terminal(void) 72013498266Sopenharmony_ci{ 72113498266Sopenharmony_ci if(InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE)) 72213498266Sopenharmony_ci SetConsoleMode(TerminalSettings.hStdOut, TerminalSettings.dwOutputMode); 72313498266Sopenharmony_ci} 72413498266Sopenharmony_ci 72513498266Sopenharmony_ci/* This is the console signal handler. 72613498266Sopenharmony_ci * The system calls it in a separate thread. 72713498266Sopenharmony_ci */ 72813498266Sopenharmony_cistatic BOOL WINAPI signal_handler(DWORD type) 72913498266Sopenharmony_ci{ 73013498266Sopenharmony_ci if(type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT) 73113498266Sopenharmony_ci restore_terminal(); 73213498266Sopenharmony_ci return FALSE; 73313498266Sopenharmony_ci} 73413498266Sopenharmony_ci 73513498266Sopenharmony_cistatic void init_terminal(void) 73613498266Sopenharmony_ci{ 73713498266Sopenharmony_ci TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 73813498266Sopenharmony_ci 73913498266Sopenharmony_ci /* 74013498266Sopenharmony_ci * Enable VT (Virtual Terminal) output. 74113498266Sopenharmony_ci * Note: VT mode flag can be set on any version of Windows, but VT 74213498266Sopenharmony_ci * processing only performed on Win10 >= version 1709 (OS build 16299) 74313498266Sopenharmony_ci * Creator's Update. Also, ANSI bold on/off supported since then. 74413498266Sopenharmony_ci */ 74513498266Sopenharmony_ci if(TerminalSettings.hStdOut == INVALID_HANDLE_VALUE || 74613498266Sopenharmony_ci !GetConsoleMode(TerminalSettings.hStdOut, 74713498266Sopenharmony_ci &TerminalSettings.dwOutputMode) || 74813498266Sopenharmony_ci !curlx_verify_windows_version(10, 0, 16299, PLATFORM_WINNT, 74913498266Sopenharmony_ci VERSION_GREATER_THAN_EQUAL)) 75013498266Sopenharmony_ci return; 75113498266Sopenharmony_ci 75213498266Sopenharmony_ci if((TerminalSettings.dwOutputMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) 75313498266Sopenharmony_ci tool_term_has_bold = true; 75413498266Sopenharmony_ci else { 75513498266Sopenharmony_ci /* The signal handler is set before attempting to change the console mode 75613498266Sopenharmony_ci because otherwise a signal would not be caught after the change but 75713498266Sopenharmony_ci before the handler was installed. */ 75813498266Sopenharmony_ci (void)InterlockedExchange(&TerminalSettings.valid, (LONG)TRUE); 75913498266Sopenharmony_ci if(SetConsoleCtrlHandler(signal_handler, TRUE)) { 76013498266Sopenharmony_ci if(SetConsoleMode(TerminalSettings.hStdOut, 76113498266Sopenharmony_ci (TerminalSettings.dwOutputMode | 76213498266Sopenharmony_ci ENABLE_VIRTUAL_TERMINAL_PROCESSING))) { 76313498266Sopenharmony_ci tool_term_has_bold = true; 76413498266Sopenharmony_ci atexit(restore_terminal); 76513498266Sopenharmony_ci } 76613498266Sopenharmony_ci else { 76713498266Sopenharmony_ci SetConsoleCtrlHandler(signal_handler, FALSE); 76813498266Sopenharmony_ci (void)InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE); 76913498266Sopenharmony_ci } 77013498266Sopenharmony_ci } 77113498266Sopenharmony_ci } 77213498266Sopenharmony_ci} 77313498266Sopenharmony_ci 77413498266Sopenharmony_ciLARGE_INTEGER tool_freq; 77513498266Sopenharmony_cibool tool_isVistaOrGreater; 77613498266Sopenharmony_ci 77713498266Sopenharmony_ciCURLcode win32_init(void) 77813498266Sopenharmony_ci{ 77913498266Sopenharmony_ci /* curlx_verify_windows_version must be called during init at least once 78013498266Sopenharmony_ci because it has its own initialization routine. */ 78113498266Sopenharmony_ci if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT, 78213498266Sopenharmony_ci VERSION_GREATER_THAN_EQUAL)) 78313498266Sopenharmony_ci tool_isVistaOrGreater = true; 78413498266Sopenharmony_ci else 78513498266Sopenharmony_ci tool_isVistaOrGreater = false; 78613498266Sopenharmony_ci 78713498266Sopenharmony_ci QueryPerformanceFrequency(&tool_freq); 78813498266Sopenharmony_ci 78913498266Sopenharmony_ci init_terminal(); 79013498266Sopenharmony_ci 79113498266Sopenharmony_ci return CURLE_OK; 79213498266Sopenharmony_ci} 79313498266Sopenharmony_ci 79413498266Sopenharmony_ci#endif /* _WIN32 */ 79513498266Sopenharmony_ci 79613498266Sopenharmony_ci#endif /* _WIN32 || MSDOS */ 797