@@ -114,7 +114,7 @@ impl Iterator for ReadDir {
114
114
fn next ( & mut self ) -> Option < io:: Result < DirEntry > > {
115
115
if self . handle . 0 == c:: INVALID_HANDLE_VALUE {
116
116
// 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
118
118
// the construction of this iterator returns `ERROR_FILE_NOT_FOUND` which means
119
119
// no matchhing files can be found.
120
120
return None ;
@@ -1047,8 +1047,22 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
1047
1047
let path = maybe_verbatim ( & star) ?;
1048
1048
1049
1049
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
+ ) ;
1052
1066
1053
1067
if find_handle != c:: INVALID_HANDLE_VALUE {
1054
1068
Ok ( ReadDir {
@@ -1057,7 +1071,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
1057
1071
first : Some ( wfd) ,
1058
1072
} )
1059
1073
} 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
1061
1075
// if no matching files can be found, but not necessarily that the path to find the
1062
1076
// files in does not exist.
1063
1077
//
@@ -1079,7 +1093,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
1079
1093
1080
1094
// Just return the error constructed from the raw OS error if the above is not the case.
1081
1095
//
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
1083
1097
// when the path to search in does not exist in the first place.
1084
1098
Err ( Error :: from_raw_os_error ( last_error. code as i32 ) )
1085
1099
}
@@ -1220,7 +1234,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
1220
1234
opts. custom_flags ( c:: FILE_FLAG_BACKUP_SEMANTICS | reparse. as_flag ( ) ) ;
1221
1235
1222
1236
// 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 `.
1224
1238
// If the fallback fails for any reason we return the original error.
1225
1239
match File :: open ( path, & opts) {
1226
1240
Ok ( file) => file. file_attr ( ) ,
@@ -1237,13 +1251,20 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
1237
1251
unsafe {
1238
1252
let path = maybe_verbatim ( path) ?;
1239
1253
1240
- // `FindFirstFileW ` accepts wildcard file names.
1254
+ // `FindFirstFileExW ` accepts wildcard file names.
1241
1255
// Fortunately wildcards are not valid file names and
1242
1256
// `ERROR_SHARING_VIOLATION` means the file exists (but is locked)
1243
1257
// therefore it's safe to assume the file name given does not
1244
1258
// 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
+ ) ;
1247
1268
1248
1269
if handle == c:: INVALID_HANDLE_VALUE {
1249
1270
// 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> {
1253
1274
// We no longer need the find handle.
1254
1275
c:: FindClose ( handle) ;
1255
1276
1256
- // `FindFirstFileW ` reads the cached file information from the
1277
+ // `FindFirstFileExW ` reads the cached file information from the
1257
1278
// directory. The downside is that this metadata may be outdated.
1258
1279
let attrs = FileAttr :: from ( wfd) ;
1259
1280
if reparse == ReparsePoint :: Follow && attrs. file_type ( ) . is_symlink ( ) {
0 commit comments