Alexandre Julliard : ntdll: Define a generic file information structure to allow supporting multiple info classes in NtQueryDirectoryFile .

Alexandre Julliard julliard at winehq.org
Thu Nov 19 10:15:17 CST 2009


Module: wine
Branch: master
Commit: cfafcc5a6ef8ccf73e07a92ea0fe7fb041f652d3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=cfafcc5a6ef8ccf73e07a92ea0fe7fb041f652d3

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Nov 18 17:42:51 2009 +0100

ntdll: Define a generic file information structure to allow supporting multiple info classes in NtQueryDirectoryFile.

---

 dlls/ntdll/directory.c |   55 +++++++++++++++++++++++++++---------------------
 1 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index f7736e2..85170aa 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -148,6 +148,12 @@ struct file_identity
 static struct file_identity ignored_files[MAX_IGNORED_FILES];
 static int ignored_files_count;
 
+union file_directory_info
+{
+    ULONG                              next;
+    FILE_BOTH_DIRECTORY_INFORMATION    both;
+};
+
 static const unsigned int max_dir_info_size = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, FileName[MAX_DIR_ENTRY_LEN] );
 
 static int show_dot_files = -1;
@@ -923,11 +929,11 @@ static BOOLEAN match_filename( const UNICODE_STRING *name_str, const UNICODE_STR
  *
  * helper for NtQueryDirectoryFile
  */
-static FILE_BOTH_DIR_INFORMATION *append_entry( void *info_ptr, IO_STATUS_BLOCK *io, ULONG max_length,
+static union file_directory_info *append_entry( void *info_ptr, IO_STATUS_BLOCK *io, ULONG max_length,
                                                 const char *long_name, const char *short_name,
                                                 const UNICODE_STRING *mask )
 {
-    FILE_BOTH_DIR_INFORMATION *info;
+    union file_directory_info *info;
     int i, long_len, short_len, total_len;
     struct stat st;
     WCHAR long_nameW[MAX_DIR_ENTRY_LEN];
@@ -984,24 +990,25 @@ static FILE_BOTH_DIR_INFORMATION *append_entry( void *info_ptr, IO_STATUS_BLOCK
     if (!show_dot_files && long_name[0] == '.' && long_name[1] && (long_name[1] != '.' || long_name[2]))
         attributes |= FILE_ATTRIBUTE_HIDDEN;
 
-    total_len = (sizeof(*info) - sizeof(info->FileName) + long_len*sizeof(WCHAR) + 3) & ~3;
+    total_len = (FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName[long_len]) + 3) & ~3;
     if (io->Information + total_len > max_length)
     {
         total_len = max_length - io->Information;
         io->u.Status = STATUS_BUFFER_OVERFLOW;
     }
 
-    info = (FILE_BOTH_DIR_INFORMATION *)((char *)info_ptr + io->Information);
-    fill_stat_info( &st, info, FileBothDirectoryInformation );
-    info->NextEntryOffset = total_len;
-    info->FileIndex = 0;  /* NTFS always has 0 here, so let's not bother with it */
-    info->FileAttributes |= attributes;
-    info->EaSize = 0; /* FIXME */
-    info->ShortNameLength = short_len * sizeof(WCHAR);
-    for (i = 0; i < short_len; i++) info->ShortName[i] = toupperW(short_nameW[i]);
-    info->FileNameLength = long_len * sizeof(WCHAR);
-    memcpy( info->FileName, long_nameW,
-            min( info->FileNameLength, total_len-sizeof(*info)+sizeof(info->FileName) ));
+    info = (union file_directory_info *)((char *)info_ptr + io->Information);
+    fill_stat_info( &st, &info->both, FileBothDirectoryInformation );
+    info->both.NextEntryOffset = total_len;
+    info->both.FileIndex = 0;  /* NTFS always has 0 here, so let's not bother with it */
+    info->both.FileAttributes |= attributes;
+    info->both.EaSize = 0; /* FIXME */
+    info->both.ShortNameLength = short_len * sizeof(WCHAR);
+    for (i = 0; i < short_len; i++) info->both.ShortName[i] = toupperW(short_nameW[i]);
+    info->both.FileNameLength = long_len * sizeof(WCHAR);
+    memcpy( info->both.FileName, long_nameW,
+            min( info->both.FileNameLength,
+                 total_len - FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, FileName )));
 
     io->Information += total_len;
     return info;
@@ -1063,7 +1070,7 @@ static int read_directory_vfat( int fd, IO_STATUS_BLOCK *io, void *buffer, ULONG
 {
     size_t len;
     KERNEL_DIRENT *de;
-    FILE_BOTH_DIR_INFORMATION *info, *last_info = NULL;
+    union file_directory_info *info, *last_info = NULL;
 
     io->u.Status = STATUS_SUCCESS;
 
@@ -1125,7 +1132,7 @@ static int read_directory_vfat( int fd, IO_STATUS_BLOCK *io, void *buffer, ULONG
         }
     }
 
-    if (last_info) last_info->NextEntryOffset = 0;
+    if (last_info) last_info->next = 0;
     else io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
     return 0;
 }
@@ -1147,7 +1154,7 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
     int res, fake_dot_dot = 1;
     char *data, local_buffer[8192];
     KERNEL_DIRENT64 *de;
-    FILE_BOTH_DIR_INFORMATION *info, *last_info = NULL;
+    union file_directory_info *info, *last_info = NULL;
 
     if (size <= sizeof(local_buffer) || !(data = RtlAllocateHeap( GetProcessHeap(), 0, size )))
     {
@@ -1251,7 +1258,7 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
         }
     }
 
-    if (last_info) last_info->NextEntryOffset = 0;
+    if (last_info) last_info->next = 0;
     else io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
     res = 0;
 done:
@@ -1320,7 +1327,7 @@ static int read_directory_getdirentries( int fd, IO_STATUS_BLOCK *io, void *buff
     int res, fake_dot_dot = 1;
     char *data, local_buffer[8192];
     struct dirent *de;
-    FILE_BOTH_DIR_INFORMATION *info, *last_info = NULL, *restart_last_info = NULL;
+    union file_directory_info *info, *last_info = NULL, *restart_last_info = NULL;
 
     size = initial_size;
     data = local_buffer;
@@ -1439,7 +1446,7 @@ static int read_directory_getdirentries( int fd, IO_STATUS_BLOCK *io, void *buff
         de = (struct dirent *)data;
     }
 
-    if (last_info) last_info->NextEntryOffset = 0;
+    if (last_info) last_info->next = 0;
     else io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
     res = 0;
 done:
@@ -1467,7 +1474,7 @@ static void read_directory_readdir( int fd, IO_STATUS_BLOCK *io, void *buffer, U
     DIR *dir;
     off_t i, old_pos = 0;
     struct dirent *de;
-    FILE_BOTH_DIR_INFORMATION *info, *last_info = NULL;
+    union file_directory_info *info, *last_info = NULL;
 
     if (!(dir = opendir( "." )))
     {
@@ -1524,7 +1531,7 @@ static void read_directory_readdir( int fd, IO_STATUS_BLOCK *io, void *buffer, U
     lseek( fd, old_pos, SEEK_SET );  /* store dir offset as filepos for fd */
     closedir( dir );
 
-    if (last_info) last_info->NextEntryOffset = 0;
+    if (last_info) last_info->next = 0;
     else io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
 }
 
@@ -1569,10 +1576,10 @@ static int read_directory_stat( int fd, IO_STATUS_BLOCK *io, void *buffer, ULONG
         ret = stat( unix_name, &st );
         if (!ret)
         {
-            FILE_BOTH_DIR_INFORMATION *info = append_entry( buffer, io, length, unix_name, NULL, NULL );
+            union file_directory_info *info = append_entry( buffer, io, length, unix_name, NULL, NULL );
             if (info)
             {
-                info->NextEntryOffset = 0;
+                info->next = 0;
                 if (io->u.Status != STATUS_BUFFER_OVERFLOW) lseek( fd, 1, SEEK_CUR );
             }
             else io->u.Status = STATUS_NO_MORE_FILES;




More information about the wine-cvs mailing list