mirror of
https://github.com/curl/curl.git
synced 2026-01-18 17:21:26 +01:00
windows: fix CreateFile() calls to support long filenames
It makes them work in Schannel's CA bundle loader, and curl tool's set/get file timestamp operations (e.g. in `-R`/`--remote-time`). Also to match file open operations, that already support long filenames. E.g. when using `--remote-time`, fixing: ``` Warning: Failed to set filetime 1741363917 on outfile: CreateFile failed: Warning: GetLastError 0x00000003 ``` The special long filename logic is necessary to support Windows releases prior to Windows 10 v1607. With the latter, it's possible to opt-in to this behavior via a manifest setting. Note that Windows itself also needs to opt-in to support this. Finally note that curl itself needs passing `--globoff` to let long filenames through, pending #20044 and #20046. Refs: https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-createfilea https://learn.microsoft.com/windows/win32/fileio/maximum-file-path-limitation Ref: #8361 Inspired by: #19286 Inspired-by: Mathesh V Closes #19286 Closes #20040
This commit is contained in:
@@ -353,6 +353,9 @@ This is the full list of functions generally banned.
|
||||
atoi
|
||||
atol
|
||||
calloc
|
||||
CreateFile
|
||||
CreateFileA
|
||||
CreateFileW
|
||||
fclose
|
||||
fdopen
|
||||
fopen
|
||||
|
||||
@@ -43,6 +43,8 @@ int curlx_fseek(void *stream, curl_off_t offset, int whence)
|
||||
|
||||
#include <share.h> /* for _SH_DENYNO */
|
||||
|
||||
#include "multibyte.h"
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
/*
|
||||
* Use system allocators to avoid infinite recursion when called by curl's
|
||||
@@ -248,6 +250,49 @@ cleanup:
|
||||
return *out ? true : false;
|
||||
}
|
||||
|
||||
#ifndef CURL_WINDOWS_UWP
|
||||
HANDLE curlx_CreateFile(const char *filename,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile)
|
||||
{
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
#ifdef UNICODE
|
||||
TCHAR *filename_t = curlx_convert_UTF8_to_wchar(filename);
|
||||
#else
|
||||
const TCHAR *filename_t = filename;
|
||||
#endif
|
||||
|
||||
if(filename_t) {
|
||||
TCHAR *fixed = NULL;
|
||||
const TCHAR *target = NULL;
|
||||
|
||||
if(fix_excessive_path(filename_t, &fixed))
|
||||
target = fixed;
|
||||
else
|
||||
target = filename_t;
|
||||
/* !checksrc! disable BANNEDFUNC 1 */
|
||||
handle = CreateFile(target,
|
||||
dwDesiredAccess,
|
||||
dwShareMode,
|
||||
lpSecurityAttributes,
|
||||
dwCreationDisposition,
|
||||
dwFlagsAndAttributes,
|
||||
hTemplateFile);
|
||||
CURLX_FREE(fixed);
|
||||
#ifdef UNICODE
|
||||
curlx_free(filename_t);
|
||||
#endif
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
#endif /* !CURL_WINDOWS_UWP */
|
||||
|
||||
int curlx_win32_open(const char *filename, int oflag, ...)
|
||||
{
|
||||
int pmode = 0;
|
||||
|
||||
@@ -35,6 +35,15 @@
|
||||
int curlx_fseek(void *stream, curl_off_t offset, int whence);
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef CURL_WINDOWS_UWP
|
||||
HANDLE curlx_CreateFile(const char *filename,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
#endif /* !CURL_WINDOWS_UWP */
|
||||
FILE *curlx_win32_fopen(const char *filename, const char *mode);
|
||||
FILE *curlx_win32_freopen(const char *filename, const char *mode, FILE *fh);
|
||||
int curlx_win32_stat(const char *path, struct_stat *buffer);
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "schannel.h"
|
||||
#include "schannel_int.h"
|
||||
|
||||
#include "../curlx/fopen.h"
|
||||
#include "../curlx/inet_pton.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
@@ -254,34 +255,24 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
CURLcode result;
|
||||
HANDLE ca_file_handle = INVALID_HANDLE_VALUE;
|
||||
HANDLE ca_file_handle;
|
||||
LARGE_INTEGER file_size;
|
||||
char *ca_file_buffer = NULL;
|
||||
TCHAR *ca_file_tstr = NULL;
|
||||
size_t ca_file_bufsize = 0;
|
||||
DWORD total_bytes_read = 0;
|
||||
|
||||
ca_file_tstr = curlx_convert_UTF8_to_tchar(ca_file);
|
||||
if(!ca_file_tstr) {
|
||||
char buffer[WINAPI_ERROR_LEN];
|
||||
failf(data, "schannel: invalid path name for CA file '%s': %s", ca_file,
|
||||
curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
|
||||
result = CURLE_SSL_CACERT_BADFILE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the CA file completely into memory before parsing it. This
|
||||
* optimizes for the common case where the CA file will be relatively
|
||||
* small ( < 1 MiB ).
|
||||
*/
|
||||
ca_file_handle = CreateFile(ca_file_tstr,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
ca_file_handle = curlx_CreateFile(ca_file,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if(ca_file_handle == INVALID_HANDLE_VALUE) {
|
||||
char buffer[WINAPI_ERROR_LEN];
|
||||
failf(data, "schannel: failed to open CA file '%s': %s", ca_file,
|
||||
@@ -347,7 +338,6 @@ cleanup:
|
||||
CloseHandle(ca_file_handle);
|
||||
}
|
||||
Curl_safefree(ca_file_buffer);
|
||||
curlx_free(ca_file_tstr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,9 @@ my %banfunc = (
|
||||
"atoi" => 1,
|
||||
"atol" => 1,
|
||||
"calloc" => 1,
|
||||
"CreateFile" => 1,
|
||||
"CreateFileA" => 1,
|
||||
"CreateFileW" => 1,
|
||||
"fclose" => 1,
|
||||
"fdopen" => 1,
|
||||
"fopen" => 1,
|
||||
|
||||
@@ -41,12 +41,9 @@ int getfiletime(const char *filename, curl_off_t *stamp)
|
||||
access to a 64-bit type we can bypass stat and get the times directly. */
|
||||
#if defined(_WIN32) && !defined(CURL_WINDOWS_UWP)
|
||||
HANDLE hfile;
|
||||
TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar(filename);
|
||||
|
||||
hfile = CreateFile(tchar_filename, FILE_READ_ATTRIBUTES,
|
||||
(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
curlx_free(tchar_filename);
|
||||
hfile = curlx_CreateFile(filename, FILE_READ_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE |
|
||||
FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if(hfile != INVALID_HANDLE_VALUE) {
|
||||
FILETIME ft;
|
||||
if(GetFileTime(hfile, NULL, NULL, &ft)) {
|
||||
@@ -93,7 +90,6 @@ void setfiletime(curl_off_t filetime, const char *filename)
|
||||
access to a 64-bit type we can bypass utime and set the times directly. */
|
||||
#if defined(_WIN32) && !defined(CURL_WINDOWS_UWP)
|
||||
HANDLE hfile;
|
||||
TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar(filename);
|
||||
|
||||
/* 910670515199 is the maximum Unix filetime that can be used as a Windows
|
||||
FILETIME without overflow: 30827-12-31T23:59:59. */
|
||||
@@ -108,10 +104,9 @@ void setfiletime(curl_off_t filetime, const char *filename)
|
||||
warnf("Capping set filetime to minimum to avoid overflow");
|
||||
}
|
||||
|
||||
hfile = CreateFile(tchar_filename, FILE_WRITE_ATTRIBUTES,
|
||||
(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
curlx_free(tchar_filename);
|
||||
hfile = curlx_CreateFile(filename, FILE_WRITE_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE |
|
||||
FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if(hfile != INVALID_HANDLE_VALUE) {
|
||||
curl_off_t converted = ((curl_off_t)filetime * 10000000) +
|
||||
116444736000000000;
|
||||
|
||||
Reference in New Issue
Block a user