@@ -2260,41 +2260,43 @@ GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(const BY_H
22602260}
22612261
22622262template <typename INFO>
2263- GHC_INLINE DWORD reparse_tag_from_INFO (const INFO*)
2263+ GHC_INLINE bool is_symlink_from_INFO (const path &p, const INFO* info, std::error_code& ec )
22642264{
2265- return 0 ;
2265+ if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
2266+ auto reparseData = detail::getReparseData (p, ec);
2267+ if (!ec && reparseData && IsReparseTagMicrosoft (reparseData->ReparseTag ) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
2268+ return true ;
2269+ }
2270+ }
2271+ return false ;
22662272}
22672273
22682274template <>
2269- GHC_INLINE DWORD reparse_tag_from_INFO (const WIN32_FIND_DATAW* info)
2275+ GHC_INLINE bool is_symlink_from_INFO (const path &, const WIN32_FIND_DATAW* info, std::error_code& )
22702276{
2271- return info->dwReserved0 ;
2277+ // dwReserved0 is undefined unless dwFileAttributes includes the
2278+ // FILE_ATTRIBUTE_REPARSE_POINT attribute according to microsoft
2279+ // documentation. In practice, dwReserved0 is not reset which
2280+ // causes it to report the incorrect symlink status.
2281+ // Note that microsoft documentation does not say whether there is
2282+ // a null value for dwReserved0, so we test for symlink directly
2283+ // instead of returning the tag which requires returning a null
2284+ // value for non-reparse-point files.
2285+ return (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && info->dwReserved0 == IO_REPARSE_TAG_SYMLINK;
22722286}
22732287
22742288template <typename INFO>
22752289GHC_INLINE file_status status_from_INFO (const path& p, const INFO* info, std::error_code& ec, uintmax_t * sz = nullptr , time_t * lwt = nullptr )
22762290{
22772291 file_type ft = file_type::unknown;
2278- if (sizeof (INFO) == sizeof (WIN32_FIND_DATAW)) {
2279- if (detail::reparse_tag_from_INFO (info) == IO_REPARSE_TAG_SYMLINK) {
2280- ft = file_type::symlink;
2281- }
2292+ if (is_symlink_from_INFO (p, info, ec)) {
2293+ ft = file_type::symlink;
22822294 }
2283- else {
2284- if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
2285- auto reparseData = detail::getReparseData (p, ec);
2286- if (!ec && reparseData && IsReparseTagMicrosoft (reparseData->ReparseTag ) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
2287- ft = file_type::symlink;
2288- }
2289- }
2295+ else if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2296+ ft = file_type::directory;
22902297 }
2291- if (ft == file_type::unknown) {
2292- if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2293- ft = file_type::directory;
2294- }
2295- else {
2296- ft = file_type::regular;
2297- }
2298+ else {
2299+ ft = file_type::regular;
22982300 }
22992301 perms prms = perms::owner_read | perms::group_read | perms::others_read;
23002302 if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
0 commit comments