diff --git boost/filesystem/path.hpp boost/filesystem/path.hpp index af5bfcc..9a93eba 100644 --- boost/filesystem/path.hpp +++ boost/filesystem/path.hpp @@ -455,7 +455,7 @@ namespace filesystem // Experimental generic function returning generic formatted path (i.e. separators // are forward slashes). Motivation: simpler than a family of generic_*string // functions. - path generic() const + path generic_path() const { # ifdef BOOST_WINDOWS_API path tmp; diff --git libs/filesystem/src/operations.cpp libs/filesystem/src/operations.cpp index b5e0f66..e85da67 100644 --- libs/filesystem/src/operations.cpp +++ libs/filesystem/src/operations.cpp @@ -10,6 +10,7 @@ //--------------------------------------------------------------------------------------// + // define 64-bit offset macros BEFORE including boost/config.hpp (see ticket #5355) #if !(defined(__HP_aCC) && defined(_ILP32) && !defined(_STATVFS_ACPP_PROBLEMS_FIXED)) #define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect, @@ -172,9 +173,11 @@ typedef struct _REPARSE_DATA_BUFFER { # define IO_REPARSE_TAG_SYMLINK (0xA000000CL) # endif +#if BOOST_PLAT_WINDOWS_RUNTIME == 0 inline std::wstring wgetenv(const wchar_t* name) { // use vector since for C++03 basic_string is not required to be contiguous + std::vector buf(::GetEnvironmentVariableW(name, NULL, 0)); // C++03 vector does not have data() so use &buf[0] @@ -182,7 +185,7 @@ inline std::wstring wgetenv(const wchar_t* name) || ::GetEnvironmentVariableW(name, &buf[0], static_cast(buf.size())) == 0) ? std::wstring() : std::wstring(&buf[0]); } - +# endif // BOOST_PLAT_WINDOWS_RUNTIME # endif // BOOST_WINDOWS_API // BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in @@ -237,8 +240,13 @@ typedef DWORD err_t; # define BOOST_CREATE_SYMBOLIC_LINK(F,T,Flag)(create_symbolic_link_api(F, T, Flag)!= 0) # define BOOST_REMOVE_DIRECTORY(P)(::RemoveDirectoryW(P)!= 0) # define BOOST_DELETE_FILE(P)(::DeleteFileW(P)!= 0) +#if BOOST_PLAT_WINDOWS_RUNTIME == 0 # define BOOST_COPY_DIRECTORY(F,T)(::CreateDirectoryExW(F, T, 0)!= 0) # define BOOST_COPY_FILE(F,T,FailIfExistsBool)(::CopyFileW(F, T, FailIfExistsBool)!= 0) +#else +# define BOOST_COPY_DIRECTORY(F,T)(::CreateDirectoryW(F, T)!= 0) +# define BOOST_COPY_FILE(F,T,FailIfExistsBool)(::CopyFile(F, T, FailIfExistsBool)!= 0) +#endif # define BOOST_MOVE_FILE(OLD,NEW)(::MoveFileExW(OLD, NEW, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED)!= 0) # define BOOST_RESIZE_FILE(P,SZ)(resize_file_api(P, SZ)!= 0) # define BOOST_READ_SYMLINK(P,T) @@ -578,13 +586,24 @@ namespace DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { +#if BOOST_PLAT_WINDOWS_RUNTIME + CREATEFILE2_EXTENDED_PARAMETERS extParams = {}; + extParams.hTemplateFile = hTemplateFile; + extParams.lpSecurityAttributes = lpSecurityAttributes; + return ::CreateFile2(p.c_str(), dwDesiredAccess, dwShareMode, + dwCreationDisposition, &extParams); +#else return ::CreateFileW(p.c_str(), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); +#endif } bool is_reparse_point_a_symlink(const path& p) { +#if BOOST_PLAT_WINDOWS_RUNTIME + return false; +#else handle_wrapper h(create_file_handle(p, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL)); @@ -610,6 +629,7 @@ namespace // with "mklink /j junction-name target-path". || reinterpret_cast(buf.get())->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT; // aka "directory junction" or "junction" +#endif } inline std::size_t get_full_path_name( @@ -643,11 +663,14 @@ namespace // _detail_directory_symlink, as required on Windows by remove() and its helpers. fs::file_type query_file_type(const path& p, error_code* ec) { - DWORD attr(::GetFileAttributesW(p.c_str())); - if (attr == 0xFFFFFFFF) + DWORD attr; + WIN32_FILE_ATTRIBUTE_DATA fileData; + + if (::GetFileAttributesExW(p.c_str(), GetFileExInfoStandard, &fileData) == 0) { return process_status_failure(p, ec).type(); } + attr = fileData.dwFileAttributes; if (ec != 0) ec->clear(); @@ -667,13 +690,22 @@ namespace BOOL resize_file_api(const wchar_t* p, boost::uintmax_t size) { +#if BOOST_PLAT_WINDOWS_RUNTIME + CREATEFILE2_EXTENDED_PARAMETERS extParams = {}; + + handle_wrapper h(::CreateFile2(p, GENERIC_WRITE, 0, + FILE_ATTRIBUTE_NORMAL, &extParams)); + return false; +#else handle_wrapper h(CreateFileW(p, GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)); + LARGE_INTEGER sz; sz.QuadPart = size; return h.handle != INVALID_HANDLE_VALUE && ::SetFilePointerEx(h.handle, sz, 0, FILE_BEGIN) && ::SetEndOfFile(h.handle); +#endif } // Windows kernel32.dll functions that may or may not be present @@ -685,19 +717,25 @@ namespace /*__reserved*/ LPSECURITY_ATTRIBUTES lpSecurityAttributes ); - PtrCreateHardLinkW create_hard_link_api = PtrCreateHardLinkW( - ::GetProcAddress( - ::GetModuleHandle(TEXT("kernel32.dll")), "CreateHardLinkW")); - typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)( /*__in*/ LPCWSTR lpSymlinkFileName, /*__in*/ LPCWSTR lpTargetFileName, /*__in*/ DWORD dwFlags ); +#if BOOST_PLAT_WINDOWS_RUNTIME + PtrCreateHardLinkW create_hard_link_api = nullptr; + + PtrCreateSymbolicLinkW create_symbolic_link_api = nullptr; +#else + PtrCreateHardLinkW create_hard_link_api = PtrCreateHardLinkW( + ::GetProcAddress( + ::GetModuleHandle(TEXT("kernel32.dll")), "CreateHardLinkW")); + PtrCreateSymbolicLinkW create_symbolic_link_api = PtrCreateSymbolicLinkW( ::GetProcAddress( ::GetModuleHandle(TEXT("kernel32.dll")), "CreateSymbolicLinkW")); +#endif #endif @@ -906,16 +944,24 @@ namespace detail # ifdef BOOST_POSIX_API struct stat from_stat; # endif - error(!BOOST_COPY_DIRECTORY(from.c_str(), to.c_str()) ? BOOST_ERRNO : 0, + error(!BOOST_COPY_DIRECTORY(from.c_str(), 0) ? BOOST_ERRNO : 0, from, to, ec, "boost::filesystem::copy_directory"); } BOOST_FILESYSTEM_DECL void copy_file(const path& from, const path& to, copy_option option, error_code* ec) { +#if BOOST_PLAT_WINDOWS_RUNTIME + COPYFILE2_EXTENDED_PARAMETERS params = {}; + params.dwCopyFlags = option == fail_if_exists ? COPY_FILE_FAIL_IF_EXISTS : 0; + error(!CopyFile2(from.c_str(), to.c_str(), + ¶ms) ? BOOST_ERRNO : 0, + from, to, ec, "boost::filesystem::copy_file"); +#else error(!BOOST_COPY_FILE(from.c_str(), to.c_str(), option == fail_if_exists) ? BOOST_ERRNO : 0, from, to, ec, "boost::filesystem::copy_file"); +#endif } BOOST_FILESYSTEM_DECL @@ -1013,7 +1059,7 @@ namespace detail void create_directory_symlink(const path& to, const path& from, system::error_code* ec) { -# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008 +# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600 || BOOST_PLAT_WINDOWS_RUNTIME // SDK earlier than Vista and Server 2008 error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec, "boost::filesystem::create_directory_symlink"); @@ -1186,8 +1232,39 @@ namespace detail return false; } +#if BOOST_PLAT_WINDOWS_RUNTIME // at this point, both handles are known to be valid + { + FILE_STANDARD_INFO info1, info2; + if (error(!::GetFileInformationByHandleEx(h1.handle, FileStandardInfo , + &info1, sizeof(info1)) ? BOOST_ERRNO : 0, p1, p2, ec, "boost::filesystem::equivalent")) + return false; + + if (error(!::GetFileInformationByHandleEx(h2.handle, FileStandardInfo , + &info2, sizeof(info2)) ? BOOST_ERRNO : 0, p1, p2, ec, "boost::filesystem::equivalent")) + return false; + + if (info1.AllocationSize.QuadPart != info2.AllocationSize.QuadPart || + info1.NumberOfLinks != info2.NumberOfLinks) { + return false; + } + } + { + FILE_BASIC_INFO info1, info2; + if (error(!::GetFileInformationByHandleEx(h1.handle, FileBasicInfo , + &info1, sizeof(info1)) ? BOOST_ERRNO : 0, p1, p2, ec, "boost::filesystem::equivalent")) + return false; + + if (error(!::GetFileInformationByHandleEx(h2.handle, FileBasicInfo , + &info2, sizeof(info2)) ? BOOST_ERRNO : 0, p1, p2, ec, "boost::filesystem::equivalent")) + return false; + if (info1.LastWriteTime.QuadPart != info2.LastWriteTime.QuadPart) { + return false; + } + } + return true; +#else BY_HANDLE_FILE_INFORMATION info1, info2; if (error(!::GetFileInformationByHandle(h1.handle, &info1) ? BOOST_ERRNO : 0, @@ -1211,7 +1288,7 @@ namespace detail == info2.ftLastWriteTime.dwLowDateTime && info1.ftLastWriteTime.dwHighDateTime == info2.ftLastWriteTime.dwHighDateTime; - +#endif # endif } @@ -1261,7 +1338,23 @@ namespace detail : static_cast(path_stat.st_nlink); # else // Windows - +#if BOOST_PLAT_WINDOWS_RUNTIME + // at this point, both handles are known to be valid + { + FILE_STANDARD_INFO info; + handle_wrapper h(create_file_handle(p.c_str(), 0, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); + + return + !error(h.handle == INVALID_HANDLE_VALUE ? + BOOST_ERRNO : 0, p, ec, "boost::filesystem::hard_link_count") + && + !error(::GetFileInformationByHandleEx(h.handle, FileStandardInfo, &info, sizeof(info))== 0 + ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::hard_link_count") + ? info.NumberOfLinks : 0; + } +#else // Link count info is only available through GetFileInformationByHandle BY_HANDLE_FILE_INFORMATION info; handle_wrapper h( @@ -1275,6 +1368,7 @@ namespace detail p, ec, "boost::filesystem::hard_link_count") ? info.nNumberOfLinks : 0; +#endif # endif } @@ -1455,21 +1549,22 @@ namespace detail || (prms & (owner_write|group_write|others_write)))) return; - DWORD attr = ::GetFileAttributesW(p.c_str()); + WIN32_FILE_ATTRIBUTE_DATA attrs; + DWORD res = ::GetFileAttributesExW(p.c_str(), GetFileExInfoStandard, &attrs); - if (error(attr == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::permissions")) + if (error(res == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::permissions")) return; if (prms & add_perms) - attr &= ~FILE_ATTRIBUTE_READONLY; + attrs.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY; else if (prms & remove_perms) - attr |= FILE_ATTRIBUTE_READONLY; + attrs.dwFileAttributes |= FILE_ATTRIBUTE_READONLY; else if (prms & (owner_write|group_write|others_write)) - attr &= ~FILE_ATTRIBUTE_READONLY; + attrs.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY; else - attr |= FILE_ATTRIBUTE_READONLY; + attrs.dwFileAttributes |= FILE_ATTRIBUTE_READONLY; - error(::SetFileAttributesW(p.c_str(), attr) == 0 ? BOOST_ERRNO : 0, + error(::SetFileAttributesW(p.c_str(), attrs.dwFileAttributes) == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::permissions"); # endif } @@ -1504,7 +1599,7 @@ namespace detail } } -# elif _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008 +# elif _WIN32_WINNT < 0x0600 || BOOST_PLAT_WINDOWS_RUNTIME // SDK earlier than Vista and Server 2008 error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::read_symlink"); # else // Vista and Server 2008 SDK, or later @@ -1681,12 +1776,14 @@ namespace detail return fs::file_status(fs::type_unknown); # else // Windows + DWORD attr; + WIN32_FILE_ATTRIBUTE_DATA fileData; - DWORD attr(::GetFileAttributesW(p.c_str())); - if (attr == 0xFFFFFFFF) + if (::GetFileAttributesExW(p.c_str(), GetFileExInfoStandard, &fileData) == 0) { return process_status_failure(p, ec); } + attr = fileData.dwFileAttributes; // reparse point handling; // since GetFileAttributesW does not resolve symlinks, try to open a file @@ -1764,12 +1861,14 @@ namespace detail return fs::file_status(fs::type_unknown); # else // Windows + DWORD attr; + WIN32_FILE_ATTRIBUTE_DATA fileData; - DWORD attr(::GetFileAttributesW(p.c_str())); - if (attr == 0xFFFFFFFF) + if (::GetFileAttributesExW(p.c_str(), GetFileExInfoStandard, &fileData) == 0) { return process_status_failure(p, ec); } + attr = fileData.dwFileAttributes; if (ec != 0) ec->clear(); @@ -1813,7 +1912,9 @@ namespace detail return p; # else // Windows - +#if BOOST_PLAT_WINDOWS_RUNTIME + return L"TEMP"; +#else const wchar_t* tmp_env = L"TMP"; const wchar_t* temp_env = L"TEMP"; const wchar_t* localappdata_env = L"LOCALAPPDATA"; @@ -1852,7 +1953,7 @@ namespace detail p /= L"Temp"; } return p; - +# endif # endif } @@ -2131,13 +2232,13 @@ namespace && dirpath[dirpath.size()-1] != L':'))? L"\\*" : L"*"; WIN32_FIND_DATAW data; - if ((handle = ::FindFirstFileW(dirpath.c_str(), &data)) - == INVALID_HANDLE_VALUE) - { + if ((handle = ::FindFirstFileExW(dirpath.c_str(), FindExInfoStandard, + &data, FindExSearchNameMatch, nullptr, 0)) == INVALID_HANDLE_VALUE) + { handle = 0; // signal eof return error_code( (::GetLastError() == ERROR_FILE_NOT_FOUND // Windows Mobile returns ERROR_NO_MORE_FILES; see ticket #3551 - || ::GetLastError() == ERROR_NO_MORE_FILES) + || ::GetLastError() == ERROR_NO_MORE_FILES) ? 0 : ::GetLastError(), system_category() ); } target = data.cFileName; diff --git libs/filesystem/src/unique_path.cpp libs/filesystem/src/unique_path.cpp index d88cbb8..3b35690 100644 --- libs/filesystem/src/unique_path.cpp +++ libs/filesystem/src/unique_path.cpp @@ -44,7 +44,7 @@ void fail(int err, boost::system::error_code* ec) return; } -#ifdef BOOST_WINDOWS_API +#if defined(BOOST_WINDOWS_API) && BOOST_PLAT_WINDOWS_RUNTIME == 0 int acquire_crypt_handle(HCRYPTPROV& handle) { @@ -104,6 +104,13 @@ void system_crypt_random(void* buf, std::size_t len, boost::system::error_code* # else // BOOST_WINDOWS_API +#if BOOST_PLAT_WINDOWS_RUNTIME + using namespace Windows::Security::Cryptography; + Windows::Storage::Streams::IBuffer^ buffer = CryptographicBuffer::GenerateRandom(len); + Platform::Array^ value; + CryptographicBuffer::CopyToByteArray(buffer, &value); + std::copy(value->begin(), value->end(), static_cast(buf)); +#else HCRYPTPROV handle; int errval = acquire_crypt_handle(handle); @@ -118,6 +125,7 @@ void system_crypt_random(void* buf, std::size_t len, boost::system::error_code* if (!errval) return; fail(errval, ec); +#endif # endif } diff --git libs/filesystem/src/windows_file_codecvt.cpp libs/filesystem/src/windows_file_codecvt.cpp index 998db60..03095ed 100644 --- libs/filesystem/src/windows_file_codecvt.cpp +++ libs/filesystem/src/windows_file_codecvt.cpp @@ -16,7 +16,7 @@ #ifndef BOOST_SYSTEM_NO_DEPRECATED # define BOOST_SYSTEM_NO_DEPRECATED #endif - +#include #include #include // for mbstate_t @@ -36,7 +36,11 @@ const char* from, const char* from_end, const char*& from_next, wchar_t* to, wchar_t* to_end, wchar_t*& to_next) const { +#if BOOST_PLAT_WINDOWS_RUNTIME + UINT codepage = CP_OEMCP; +#else UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; +#endif int count; if ((count = ::MultiByteToWideChar(codepage, MB_PRECOMPOSED, from, @@ -56,7 +60,11 @@ const wchar_t* from, const wchar_t* from_end, const wchar_t* & from_next, char* to, char* to_end, char* & to_next) const { +#if BOOST_PLAT_WINDOWS_RUNTIME + UINT codepage = CP_OEMCP; +#else UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; +#endif int count; if ((count = ::WideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, from,