@@ -114,7 +114,7 @@ impl Iterator for ReadDir {
114114 fn next ( & mut self ) -> Option < io:: Result < DirEntry > > {
115115 if self . handle . 0 == c:: INVALID_HANDLE_VALUE {
116116 // This iterator was initialized with an `INVALID_HANDLE_VALUE` as its handle.
117- // Simply return `None` because this is only the case when `FindFirstFileW ` in
117+ // Simply return `None` because this is only the case when `FindFirstFileExW ` in
118118 // the construction of this iterator returns `ERROR_FILE_NOT_FOUND` which means
119119 // no matchhing files can be found.
120120 return None ;
@@ -1047,8 +1047,22 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
10471047 let path = maybe_verbatim ( & star) ?;
10481048
10491049 unsafe {
1050- let mut wfd = mem:: zeroed ( ) ;
1051- let find_handle = c:: FindFirstFileW ( path. as_ptr ( ) , & mut wfd) ;
1050+ let mut wfd: c:: WIN32_FIND_DATAW = mem:: zeroed ( ) ;
1051+ // this is like FindFirstFileW (see https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstfileexw),
1052+ // but with FindExInfoBasic it should skip filling WIN32_FIND_DATAW.cAlternateFileName
1053+ // (see https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-win32_find_dataw)
1054+ // (which will be always null string value and currently unused) and should be faster.
1055+ //
1056+ // We can pass FIND_FIRST_EX_LARGE_FETCH to dwAdditionalFlags to speed up things more,
1057+ // but as we don't know user's use profile of this function, lets be conservative.
1058+ let find_handle = c:: FindFirstFileExW (
1059+ path. as_ptr ( ) ,
1060+ c:: FindExInfoBasic ,
1061+ & mut wfd as * mut _ as _ ,
1062+ c:: FindExSearchNameMatch ,
1063+ ptr:: null ( ) ,
1064+ 0 ,
1065+ ) ;
10521066
10531067 if find_handle != c:: INVALID_HANDLE_VALUE {
10541068 Ok ( ReadDir {
@@ -1057,7 +1071,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
10571071 first : Some ( wfd) ,
10581072 } )
10591073 } else {
1060- // The status `ERROR_FILE_NOT_FOUND` is returned by the `FindFirstFileW ` function
1074+ // The status `ERROR_FILE_NOT_FOUND` is returned by the `FindFirstFileExW ` function
10611075 // if no matching files can be found, but not necessarily that the path to find the
10621076 // files in does not exist.
10631077 //
@@ -1079,7 +1093,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
10791093
10801094 // Just return the error constructed from the raw OS error if the above is not the case.
10811095 //
1082- // Note: `ERROR_PATH_NOT_FOUND` would have been returned by the `FindFirstFileW ` function
1096+ // Note: `ERROR_PATH_NOT_FOUND` would have been returned by the `FindFirstFileExW ` function
10831097 // when the path to search in does not exist in the first place.
10841098 Err ( Error :: from_raw_os_error ( last_error. code as i32 ) )
10851099 }
@@ -1220,7 +1234,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
12201234 opts. custom_flags ( c:: FILE_FLAG_BACKUP_SEMANTICS | reparse. as_flag ( ) ) ;
12211235
12221236 // Attempt to open the file normally.
1223- // If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileW `.
1237+ // If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileExW `.
12241238 // If the fallback fails for any reason we return the original error.
12251239 match File :: open ( path, & opts) {
12261240 Ok ( file) => file. file_attr ( ) ,
@@ -1237,13 +1251,20 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
12371251 unsafe {
12381252 let path = maybe_verbatim ( path) ?;
12391253
1240- // `FindFirstFileW ` accepts wildcard file names.
1254+ // `FindFirstFileExW ` accepts wildcard file names.
12411255 // Fortunately wildcards are not valid file names and
12421256 // `ERROR_SHARING_VIOLATION` means the file exists (but is locked)
12431257 // therefore it's safe to assume the file name given does not
12441258 // include wildcards.
1245- let mut wfd = mem:: zeroed ( ) ;
1246- let handle = c:: FindFirstFileW ( path. as_ptr ( ) , & mut wfd) ;
1259+ let mut wfd: c:: WIN32_FIND_DATAW = mem:: zeroed ( ) ;
1260+ let handle = c:: FindFirstFileExW (
1261+ path. as_ptr ( ) ,
1262+ c:: FindExInfoBasic ,
1263+ & mut wfd as * mut _ as _ ,
1264+ c:: FindExSearchNameMatch ,
1265+ ptr:: null ( ) ,
1266+ 0 ,
1267+ ) ;
12471268
12481269 if handle == c:: INVALID_HANDLE_VALUE {
12491270 // This can fail if the user does not have read access to the
@@ -1253,7 +1274,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
12531274 // We no longer need the find handle.
12541275 c:: FindClose ( handle) ;
12551276
1256- // `FindFirstFileW ` reads the cached file information from the
1277+ // `FindFirstFileExW ` reads the cached file information from the
12571278 // directory. The downside is that this metadata may be outdated.
12581279 let attrs = FileAttr :: from ( wfd) ;
12591280 if reparse == ReparsePoint :: Follow && attrs. file_type ( ) . is_symlink ( ) {
0 commit comments