diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index cbfc022be8055e7c6499d745ca8d2b68591e8575..81b5c2e7794a0c185f933a169a9fd19b64ba3b1f 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -2112,6 +2112,77 @@ done: return ret; } +#ifdef HAVE_GETATTRLIST +/*********************************************************************** + * read_directory_getattrlist + * + * Read a single file from a directory by determining whether the file + * identified by mask exists using getattrlist. + */ +static int read_directory_getattrlist( int fd, IO_STATUS_BLOCK *io, void *buffer, ULONG length, + BOOLEAN single_entry, const UNICODE_STRING *mask, + BOOLEAN restart_scan, FILE_INFORMATION_CLASS class ) +{ + int unix_len, ret, used_default; + char *unix_name; + struct attrlist attrlist; + struct + { + u_int32_t length; + struct attrreference name_reference; + char name[NAME_MAX + 1]; + } attrlist_buffer; + + TRACE("looking up file %s\n", debugstr_us( mask )); + + unix_len = ntdll_wcstoumbs( 0, mask->Buffer, mask->Length / sizeof(WCHAR), NULL, 0, NULL, NULL ); + if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len + 1))) + { + io->u.Status = STATUS_NO_MEMORY; + return 0; + } + ret = ntdll_wcstoumbs( 0, mask->Buffer, mask->Length / sizeof(WCHAR), unix_name, unix_len, + NULL, &used_default ); + if (ret > 0 && !used_default) + { + unix_name[ret] = 0; + if (restart_scan) + { + lseek( fd, 0, SEEK_SET ); + } + else if (lseek( fd, 0, SEEK_CUR ) != 0) + { + io->u.Status = STATUS_NO_MORE_FILES; + ret = 0; + goto done; + } + + memset( &attrlist, 0, sizeof(attrlist) ); + attrlist.bitmapcount = ATTR_BIT_MAP_COUNT; + attrlist.commonattr = ATTR_CMN_NAME; + ret = getattrlist( unix_name, &attrlist, &attrlist_buffer, sizeof(attrlist_buffer), 0 ); + if (!ret) + { + union file_directory_info *info = append_entry( buffer, io, length, attrlist_buffer.name, NULL, NULL, class ); + if (info) + { + info->next = 0; + if (io->u.Status != STATUS_BUFFER_OVERFLOW) lseek( fd, 1, SEEK_CUR ); + } + else io->u.Status = STATUS_NO_MORE_FILES; + } + } + else ret = -1; + +done: + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); + + TRACE("returning %d\n", ret); + + return ret; +} +#endif + /****************************************************************************** * NtQueryDirectoryFile [NTDLL.@] @@ -2173,9 +2244,15 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, if ((read_directory_vfat( fd, io, buffer, length, single_entry, mask, restart_scan, info_class )) != -1) goto done; #endif - if (!has_wildcard( mask ) && - read_directory_stat( fd, io, buffer, length, single_entry, + if (!has_wildcard( mask )) + { +#ifdef HAVE_GETATTRLIST + if (read_directory_getattrlist( fd, io, buffer, length, single_entry, mask, restart_scan, info_class ) != -1) goto done; +#endif + if (read_directory_stat( fd, io, buffer, length, single_entry, + mask, restart_scan, info_class ) != -1) goto done; + } #ifdef USE_GETDENTS if ((read_directory_getdents( fd, io, buffer, length, single_entry, mask, restart_scan, info_class )) != -1) goto done;